前言:上一节我们学习了MyBatis的简单实现CRUD,在这个过程中我们用了原始的Dao的方法开发,在这个过程中我们发现存在一些弊端,如有很多重复的代码,sqlSession的操作,statement中id的硬编码给将来维护带来不便等等,这也是很多程序员苦恼的,因此推荐Mapper代理开发,简单高效,毕竟学习的过程总是先苦后甜.下面我们来一起研究Mapper代理开发.
一、基于Mapper的代理开发方式
在使用MyBatis开发Dao是,通常有两种方法,即原始Dao方法,和基于Mapper接口的方法,MyBatis在进行Dao开发时,一般会涉及到三姐妹,分别是SqlSessionFactoryBuilder、SqlSessionFactiory、SqlSession。
我们都知道SqlSession中封装了对数据库的操作,如增删改查,通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是由SqlSessionFactoryBuilder创建的.
1. SqlSessionFactoryBuilder
SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
2.SqlSessionFactory
SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
3.SqlSession
SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。
SqlSession中提供了很多操作数据库的方法:如:selectOne(返回单个对象)、selectList(返回单个或多个对象),SqlSession是线程不安全的,在SqlSesion实现类中除了有接口中的方法(操作数据库的方法)还有数据域属性,SqlSession最佳应用场合在方法体内,定义成局部变量使用,绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。今天的博文中,小编将着重介绍小伙伴们介绍mybatis中开发dao的两种方法,原始dao的开发方式和mapper代理开发。
mybatis 中 dao 的开发方法,分别是原始 dao 的开发和 mapper 代理开发,原始Dao开发和Mapper动态代理开发,这两种各有优点。原始Dao开发:程序员要写Dao和Dao实现,需要些较多的代码,但是比较好理解。Mapper动态代理:程序员只需要写Mapper接口,然后按照规范进行配置,MyBatis就会自动实现类似Dao实现,减少模板方法。mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。
二、Mapper代理开发的实列
1. Mapper代理开发的一些规则
*xxxmapper.xml中的namespace等于mapper接口地址
*xxxmapper.java接口中的方法 xxxmapper.xml中的statement的id一致
*xxxmapper.java接口中的方法输入参数和xxxmapper.xml中statement的parameterType指定类型一致
*xxxmapper.java接口中的方法的返回值类型和xxxmapper.xml中resultType指定的类型一致
2.MyBatis的开发过程
☐ 编写MyBatis的配置文件MyBatis-config.xml
☐ 编写MyBatis的映射文件xxxmapper.xml(这里主要是statement和sql语句)
☐ 编写MyBatis的接口方法xxxmapper.java(注意这里方法名与映射文件中的statement一致)
☐ 通过SqlSessionFactory获取SqlSession
☐ 通过SqlSesson操作数据库(执行CRUD需要调用的SqlSession.commit()
☐ SqlSession使用完关闭数据库
3.首先创建一个user数据库
use mybatis;
create table user(
id int null auto_increment,
name varchar(32) not null,
password varchar(32) not null,
age int not null,
create_time datetime null,
primary key(id)
);
4.加入日志包,创建一个mybatis-config.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 开启驼峰命名法规则,create_time 就等于createTime -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 默认引用那个数据库环境 -->
<environments default="development">
<environment id="development">
<!-- 事务管理方式 -->
<transactionManager type="JDBC" />
<!-- 数据库连接四要素 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- SQL的映射文件 -->
<mappers>
<mapper resource="com/dqsy/mybatis/mapper/UserMapper.xml" />
</mappers>
</configuration>
5.创建一个UserMapper.xml的映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dqsy.mybatis.mapper.UserMapper">
<!--
id:表示一个SQL句柄,相当于JDBC中的statement
parametaerType:输入参数的类型,在SQL语句中,通过占位符#{}来接受参数
resultType:SQL操作的返回结果类型
-->
<!-- 单个查询 -->
<select id="getUserById" parameterType="java.lang.Integer"
resultType="com.dqsy.mybatis.entity.User">
select id,name,password,age,create_time from user where id=#{id}
</select>
<!-- 查询列表 -->
<select id="getUserList" resultType="com.dqsy.mybatis.entity.User">
select id,name,password,age,create_time from user
</select>
<!-- 添加用户 注意在这传参是java里的参数 而不是数据库里的字段名-->
<select id="addUser" parameterType="com.dqsy.mybatis.entity.User">
insert into user(name,password,age,create_time) values(#{name}, #{password} ,#{age}, #{createTime})
</select>
<!-- 删除用户 -->
<select id="delUser" parameterType="java.lang.Integer">
delete from user where id = #{id}
</select>
<!-- 修改用户的数据 -->
<select id="uptUser" parameterType="com.dqsy.mybatis.entity.User">
update user set name=#{name}, password=#{password}, age=#{age}, create_time=#{createTime} where id=#{id}
</select>
</mapper>
6.同时在该包下创建一个与映射文件对应的UserMapper.java的接口
package com.dqsy.mybatis.mapper;
import java.util.List;
import com.dqsy.mybatis.entity.User;
public interface UserMapper {
public User getUserById(int id);
public List<User> getUserList();
public void addUser(User user);
public void delUser(int i);
public void uptUser(User user);
}
7.创建一个User的实体类(并实现getset方法和tostring方法)
public class User {
private int id;
private String name;
private String password;
private int age;
private Date createTime;
8.建立一个测试类MapperTest
package com.dqsy.mybatis.test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import com.dqsy.mybatis.entity.User;
import com.dqsy.mybatis.mapper.UserMapper;
public class MapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException{
String configFile = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(configFile);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void TestGetUserById(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
System.out.println(userMapper.getUserById(1));
sqlSession.close();
}
//查询用户
@Test
public void TestGetUserList(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> users = userMapper.getUserList();
for(User u: users){
System.out.println(u);
}
sqlSession.close();
}
//添加用户
@Test
public void TestAddUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setName("鲁金环");
user.setPassword("123");
user.setAge(23);
user.setCreateTime(new Date());
userMapper.addUser(user);
sqlSession.commit();
sqlSession.close();
}
//删除用户
@Test
public void TestdelUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.delUser(1);
sqlSession.commit();
sqlSession.close();
}
//修改用户
@Test
public void TestuptUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(2);
user.setName("王巍");
user.setPassword("123");
user.setAge(23);
user.setCreateTime(new Date());
userMapper.uptUser(user);
sqlSession.commit();
sqlSession.close();
}
}
8.测试结果在这我就截一下数据库的图就行
在这注意下整个包的结构
三、总结(#{}和${}的区别)
#{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,#{}中可以写成value或其它名称。
#{}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
${}表示一个拼接符号,会引用sql注入,所以不建议使用${}。
${}接收输入参数,类型可以是简单类型,pojo、hashmap。
如果接收简单类型,${}中只能写成value。
${}接收pojo对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性...的方式获取对象属性值。
selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方 法,如果返回单个对象则调用selectOne方法。
namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。