1.原始Dao开发方式
原始Dao开发方法需要程序员编写Dao接口和Dao实现类。
1.映射文件:(user.xml)
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="test"><select id="findUserById" parameterType="int" resultType="com.huihui.pojo.User"> select * from user where id=#{id}</select><select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User"> select * from user where username like '%${value}%'</select><insert id="insertUser" parameterType="com.huihui.pojo.User" > insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey></insert><delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{id}</delete><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 { 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{ 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>
5.测试代码:
public class UserDaoImplTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception{ String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ UserDao userDao = new UserDaoImpl(sqlSessionFactory); User user = userDao.findUserById(1); System.out.println(user); } @Test public void testFindUserByName() throws Exception{ UserDao userDao = new UserDaoImpl(sqlSessionFactory); 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.映射文件(UserMapper.xml文件):
定义mapper映射文件UserMapper.xml(内容同User.xml一样),需要修改namespace的值为UserMapper接口路径。将UserMapper.xml放在classpath下mapper目录下。
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.huihui.mapper.UserMapper"><select id="findUserById" parameterType="java.lang.Integer" resultType="com.huihui.pojo.User"> select * from user where id=#{id}</select><select id="findUserByUsername" parameterType="java.lang.String" resultType="com.huihui.pojo.User"> select * from user where username like '%${value}%'</select><insert id="insertUser" parameterType="com.huihui.pojo.User" > insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> select LAST_INSERT_ID() </selectKey></insert><delete id="deleteUser" parameterType="java.lang.Integer"> delete from user where id = #{id}</delete><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 { 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>
4.测试代码:
package com.huihui.mapperimport java.io.InputStreamimport java.util.Dateimport java.util.Listimport org.apache.ibatis.io.Resourcesimport org.apache.ibatis.session.SqlSessionimport org.apache.ibatis.session.SqlSessionFactoryimport org.apache.ibatis.session.SqlSessionFactoryBuilderimport org.junit.Beforeimport org.junit.Testimport com.huihui.pojo.Userpublic 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方法中不建议使用包装类型(原因:不利于业务层的可扩展)。