原始dao和Mapper动态代理的开放方式---Mybatis学习笔记(六)
2017-08-16 21:22
531 查看
1.原始Dao开发方式
原始Dao开发方法需要程序员编写Dao接口和Dao实现类。 1.映射文件:(user.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"> <!-- namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用。 --> <mapper namespace="test"> <!-- 根据Id获取用户信息 ,返回一条数据--> <!-- 通过<select>进行数据库查询 id:标识映射文件中的sql 将sql语句封装到mappedStatement对象中,所以将id称为statement的id parameterType:指定输入参数的类型 #{}:表示一个占位符 #{id}:其中的id表示接收输入的参数,参数的名称就是id,如果输入参数为简单类型,#{}中的参数名可以任意,可以value也可以其它名称。 resultType:指定sql输出结果的所映射的java对象类型。select指定resultType表示将单条记录映射成的java对象。 --> <select id="findUserById" parameterType="int" resultType="com.huihui.pojo.User"> select * from user where id=#{id} </select> <!-- 自定义条件查询用户列表,可能返回多条 --> <!-- ${}:表示拼接sql串,将接收到的参数的内容不加任何修饰拼接到sql中。 使用${}拼接sql,可能引起sql注入 ${value}:接收输入参数的内容,如果传入的类型是简单类型,${}中只能使用value --> <select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User"> select * from user where username like '%${value}%' </select> <!-- 添加用户 --> <!-- parameterType:指定输入参数类型为pojo #{}中指定pojo的属性名,接收到pojo对象的属性值 --> <insert id="insertUser" parameterType="com.huihui.pojo.User" > insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) <!-- selectKey将主键返回,需要再返回 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey> </insert> <!-- 删除用户 --> <!-- 根据id删除用户,需要输入id值 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{id} </delete> <!-- 更新用户 --> <!-- 根据id更新用户,需要传入用户的id和用户的更新信息(也就是传入User对象,但是user对象中的id必须存在) --> <update id="updateUser" parameterType="com.huihui.pojo.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2.Dao接口:
package com.huihui.dao; import java.util.List; import com.huihui.pojo.User; public interface UserDao { //根据id查询用户信息 public User findUserById(int id) throws Exception; //根据用户的名称查询用户的信息 public List<User> findUserByName(String name) throws Exception; //添加用户信息 public void insertUser(User user) throws Exception; //删除用户信息 public void deleteUser(int id) throws Exception; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
3.Dao接口实现类:
package com.huihui.dao; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import com.huihui.pojo.User; public class UserDaoImpl implements UserDao{ //需要向dao实现类中注入SqlSessionFactory //这里通过构造方法注入 private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } @Override public User findUserById(int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById", id); //释放资源 sqlSession.close(); return user; } @Override public void insertUser(User user) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.insert("test.insertUser", user); //提交事务 sqlSession.commit(); //释放资源 sqlSession.close(); } @Override public void deleteUser(int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("test.deleteUser", id); //提交事务 sqlSession.commit(); //释放资源 sqlSession.close(); } @Override public List<User> findUserByName(String name) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.selectList("test.findUserByUsername", name); //释放资源 sqlSession.close(); return null; } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
4.加载user.xml文件
修改SqlMapConfig.xml文件:
<!-- 加载映射文件 --> <mappers> <mapper resource="sqlmap/user.xml"/> </mappers>1
2
3
4
5
1
2
3
4
5
5.测试代码:
public class UserDaoImplTest { private SqlSessionFactory sqlSessionFactory; @Before //此方法是运行下面的测试用例的方法之前执行的 public void setUp() throws Exception{ //创建sqlSessionFactory //mybatis配置文件路径 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //创建会话工厂,传入mybatis的配置文件信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ //创建一个userDao的对象 UserDao userDao = new UserDaoImpl(sqlSessionFactory); //调用UserDao方法 User user = userDao.findUserById(1); System.out.println(user); } @Test public void testFindUserByName() throws Exception{ //创建一个userDao对象 UserDao userDao = new UserDaoImpl(sqlSessionFactory); //调用UserDao方法 List<User> list = userDao.findUserByName("张"); System.out.println(list.size()); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
分析原始Dao开发方式存在的问题:
原始Dao开发中存在以下问题:Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
调用sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。
调用sqlsession方法时传入的变量,由于sqlsession方法使用泛型,即使变量类型传入错误,在编译阶段也不报错,不利于程序员开发。
2.mapper动态代理的方法
实现原理 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
Mapper.xml文件中的namespace与mapper接口的类路径相同。
Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
只有遵循以上规范,mybatis才可以自动生成mapper接口的实现类代理对象。
其实以上的规范主要为了相对于dao实现类中的以下方法进行了自动生成:
User user = sqlSession.selectOne("test.findUserById", id); sqlSession.insert("test.insertUser", user); sqlSession.delete("test.deleteUser", id); sqlSession.selectList("test.findUserByUsername", name); ...1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
1.映射文件(UserMapper.xml文件):
定义mapper映射文件UserMapper.xml(内容同User.xml一样),需要修改namespace的值为UserMapper接口路径。将UserMapper.xml放在classpath下mapper目录下。
<?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"> <!-- namespace :命名空间,用于隔离sql语句,后面会讲另一层非常重要的作用(需要修改namespace的值为UserMapper接口路径)。 --> <mapper namespace="com.huihui.mapper.UserMapper"> <!-- 根据Id获取用户信息 ,返回一条数据--> <!-- 通过<select>进行数据库查询 id:标识映射文件中的sql 将sql语句封装到mappedStatement对象中,所以将id称为statement的id parameterType:指定输入参数的类型 #{}:表示一个占位符 #{id}:其中的id表示接收输入的参数,参数的名称就是id,如果输入参数为简单类型,#{}中的参数名可以任意,可以value也可以其它名称。 resultType:指定sql输出结果的所映射的java对象类型。select指定resultType表示将单条记录映射成的java对象。 --> <select id="findUserById" parameterType="java.lang.Integer" resultType="com.huihui.pojo.User"> select * from user where id=#{id} </select> <!-- 自定义条件查询用户列表,可能返回多条 --> <!-- ${}:表示拼接sql串,将接收到的参数的内容不加任何修饰拼接到sql中。 使用${}拼接sql,可能引起sql注入 ${value}:接收输入参数的内容,如果传入的类型是简单类型,${}中只能使用value --> <select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User"> select * from user where username like '%${value}%' </select> <!-- 添加用户 --> <!-- parameterType:指定输入参数类型为pojo #{}中指定pojo的属性名,接收到pojo对象的属性值 --> <insert id="insertUser" parameterType="com.huihui.pojo.User" > insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) <!-- selectKey将主键返回,需要再返回 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey> </insert> <!-- 删除用户 --> <!-- 根据id删除用户,需要输入id值 --> <delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{id} </delete> <!-- 更新用户 --> <!-- 根据id更新用户,需要传入用户的id和用户的更新信息(也就是传入User对象,但是user对象中的id必须存在) --> <update id="updateUser" parameterType="com.huihui.pojo.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2.接口(UserMapper.Java文件)
接口定义有如下特点:
Mapper接口方法名和Mapper.xml中定义的statement的id相同
Mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同
Mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同
package com.huihui.mapper; import java.util.List; import com.huihui.pojo.User; /** * mapper接口,相当于dao接口 * 用户管理 * @author 62347 * */ public interface UserMapper { //根据id查询用户信息 public User findUserById(int id) throws Exception; //根据用户名列查询用户列表 public List<User> findUserByUsername(String name) throws Exception; //添加用户信息 public void insertUser(User user) throws Exception; //删除用户信息 public void deleteUser(int id) throws Exception; }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
3.加载UserMapper.xml文件
<!-- 加载映射文件 --> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers>1
2
3
4
5
1
2
3
4
5
4.测试代码:
package com.huihui.mapper; 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.huihui.pojo.User; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before //此方法是运行下面的测试用例的方法之前执行的 public void setUp() throws Exception{ //创建sqlSessionFactory //mybatis配置文件路径 String resource = "SqlMapConfig.xml"; //得到配置文件流 InputStream inputStream = Resources.getResourceAsStream(resource); //创建会话工厂,传入mybatis的配置文件信息 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception { //通过会话工厂得到会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //创建UserMapper对象,mybatis自动生成mapper代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findUserById(30); System.out.println(user); sqlSession.close(); } @Test public void testFindUserByName() throws Exception { //通过会话工厂得到会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //创建UserMapper对象,mybatis自动生成mapper代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> list = userMapper.findUserByUsername("张"); System.out.println(list.size()); sqlSession.close(); } @Test public void testInsertUser() throws Exception { //通过会话工厂得到会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //创建UserMapper对象,mybatis自动生成mapper代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setSex("2"); user.setBirthday(new Date()); user.setAddress("北京丰台"); user.setUsername("哒哒哒"); userMapper.insertUser(user); sqlSession.commit();//提交事务 sqlSession.close(); } @Test public void testDeleteUser() throws Exception { //通过会话工厂得到会话 SqlSession sqlSession = sqlSessionFactory.openSession(); //创建UserMapper对象,mybatis自动生成mapper代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.deleteUser(30); sqlSession.commit();//提交事务 sqlSession.close(); } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
重点说明:
selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。
mapper接口输入参数只能有一个,是否不利于系统扩展维护?
系统框架中,dao层的代码是被业务层公用的。即使mapper接口中只有一个参数,也可以使用包装类型的pojo满足不同的业务方法的需求。
注意:持久层中方法的参数可以是包装类型(eg:map,…..),但是service方法中不建议使用包装类型(原因:不利于业务层的可扩展)。
相关文章推荐
- 原始dao和Mapper动态代理的开放方式---Mybatis学习笔记(六)
- MyBatis学习记录(3):Mapper动态代理方式开发DAO
- Mybatis学习笔记(4)--MyBatis的Mapper动态代理方式
- mybatis3整合spring4-采用mapper动态代理的方式开发Dao
- myBatis中原始dao开发方式与Mapper代理方式
- spring整合mybatis(原始dao和mapper代理两种方式)
- Mybatis学习(2)原始dao开发和使用mapper接口代理开发
- Spring+SpringMVC+MyBatis深入学习及搭建(二)——MyBatis原始Dao开发和mapper代理开发
- mybatis--开发Dao--原始dao方式和Mapper代理方式
- mybatis学习之原始开发DAO与mapper代理开发DAO的区别
- Spring+SpringMVC+MyBatis深入学习及搭建(二)之MyBatis原始Dao开发和mapper代理开发
- 【Spring+SpringMVC+MyBatis深入学习及搭建】02.MyBatis原始Dao开发和mapper代理开发
- Mybatis框架学习二——DAO开发方式和Mapper代理的开发方式
- JavaWeb学习笔记-mybatis-08-dao开发使用(mapper代理开发)
- Mybatis实现Mapper动态代理方式
- Mybatis Mapper动态代理方法 即 只写Dao接口 不谢Dao的实现类
- 【MyBatis学习04】mapper代理方法开发dao
- 【MyBatis框架点滴】——MyBatis开发DAO的两种方法:原始DAO开发方法和Mapper代理方法
- Mybatis (三)原始DAO开发和mapper代理方法
- 【MyBatis学习04】mapper代理方法开发dao