Mybatis 增删改查之dao层实现

1.背景

   在上篇中我们使用了MyBatis实现简单的增删改查,并没有进行dao层的封装,所以在这里我们进行dao层开发:

   (1)传统的jdbc dao层开发(写dao接口,实现dao接口类)

   (2)mapper代理方法 (只需要写mapper接口类,相当于dao接口类)

     在Mybatis操作的时候,我们使用的是SqlSession 来进行数据库操作,其中SqlSession的使用范围:
     通过SqlSessionFactoryBuilder创建SqlSessionFactory ,而SqlSession通过SqlSessionFactory 创建,所以使用单例模式管理SqlSessionFactory,将来使用mybatis和spring整合后,使用单例模式管理SqlSessionFactory;
      

     SqlSession的作用是:
            1)提供接口,很多操作数据库的方法,如:selectOne ,selectList
  2)线程不安全,在sqlSession实现类中除了有接口中的方法,还有数据域的属性;
  3)最佳应用的场合在方法体内,定义成局部变量使用。

 

2.原始dao开发实现

   (1)dao接口

 

[java] view plain copy
 
  1. package mybatie.dao;  
  2.   
  3. import mybatis.po.FClient;  
  4.   
  5.   
  6. /** 
  7.  * 用户接口 
  8.  * 
  9.  * 作者:原明卓 
  10.  * 时间:2015年12月21日 上午10:00:00 
  11.  * 描述:TODO 
  12.  */  
  13. public interface ClientDao {  
  14.       
  15.     FClient findClientById(int id) throws Exception;  
  16.       
  17.     void updateClient(FClient f)  throws Exception;  
  18.       
  19.     void deleteClient(int id) throws Exception;  
  20.   
  21.     void insertClient(FClient f) throws Exception;  
  22.       
  23. }  

 

    (2)实现dao接口

 

             实现数据库操作的几个方法:

 

[java] view plain copy
 
  1. package mybatie.dao;  
  2.   
  3. import mybatis.po.FClient;  
  4. import oracle.net.aso.s;  
  5.   
  6. import org.apache.ibatis.session.SqlSession;  
  7. import org.apache.ibatis.session.SqlSessionFactory;  
  8.   
  9. public class ClientDaoImp implements ClientDao {  
  10.   
  11.     private SqlSessionFactory sqlSessionFactory;  
  12.   
  13.     public ClientDaoImp(SqlSessionFactory sqlSessionFactory) {  
  14.         this.sqlSessionFactory = sqlSessionFactory;  
  15.     }  
  16.   
  17.     @Override  
  18.     public FClient findClientById(int id) {  
  19.   
  20.         SqlSession sqlSession = sqlSessionFactory.openSession();  
  21.         FClient c = sqlSession.selectOne("test.findClientById", id);  
  22.         sqlSession.close();  
  23.         return c;  
  24.     }  
  25.   
  26.     @Override  
  27.     public void updateClient(FClient f) {  
  28.         SqlSession sqlSession=sqlSessionFactory.openSession();  
  29.         sqlSession.update("test.updateClient",f);  
  30.         sqlSession.commit();  
  31.         sqlSession.close();  
  32.     }  
  33.   
  34.     @Override  
  35.     public void deleteClient(int id) {  
  36.           SqlSession session = sqlSessionFactory.openSession();  
  37.           session.delete("test.deleteClient", id);  
  38.           session.commit();  
  39.           session.close();  
  40.     }  
  41.   
  42.     @Override  
  43.     public void insertClient(FClient f) {  
  44.         SqlSession session = sqlSessionFactory.openSession();  
  45.         session.insert("test.insertClient", f);  
  46.         session.commit();  
  47.         session.close();   
  48.     }  
  49.       
  50.   
  51. }  



 

   (3)测试类

 

[java] view plain copy
 
  1. public class TestClient {  
  2.   
  3.     private SqlSessionFactory sqlSessionFactory;  
  4.   
  5.     @Before  
  6.     public void setUp() throws Exception {  
  7.         InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");  
  8.         sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);  
  9.     }  
  10.   
  11.     @Test  
  12.     public void test() {  
  13.         fail("Not yet implemented");  
  14.     }  
  15.   
  16.     @Test  
  17.     public void findClientById() throws Exception {  
  18.   
  19.         ClientDao clientDao = new ClientDaoImp(sqlSessionFactory);  
  20.         FClient c = clientDao.findClientById(1);  
  21.         System.out.println(c);  
  22.     }  
  23.   
  24. }  

 

    (4)原始的dao层遇到的问题

 

             1)dao接口实现类方法中存在大量的模板方法,设想能否将这些代码提取出来
     2)调用sqlsession方法的时候将statement存在硬编码
     3)调用sqlsession的方法的时候,传入参数为Object 类型,及时传入错误,也不会报错

 

3.使用Mapper代理的方式实现

      基本步骤为 :   

             1)编写mapper.xml映射文件 

             2)编写Mapper接口,相当于dao接口 

             3)mybatis可以自动生成mapper接口的实现类代理对象

    (1)实现Mapper映射文件

              mapper.xml 规范 :
 1)namespace 等于mapper接口地址
 2)mapper.Java 接口中的方法和mapper.xml中的statement 的id一致
 3)mapper.java 接口中的方法的参数和mapper.xml中的statement 的paramterType类型一致
 4)mapper.java 接口中的方法的返回值和mapper.xml中的statement的resultType类型一致
 
总结 :mapper.xml实现的规范,就是对SqlSession接口中的方法进行统一的生成

       比如 :

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper  
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.   
  6. <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 -->  
  7. <!-- 注意:使用mapper代理的方法开发,namespace有特殊的重要作用,namespace为mapper接口的地址 -->  
  8.   
  9. <mapper namespace="mybatie.mapper.ClientMapper">  
  10.   
  11.     <!-- 在映射文件中配置很多的sql语句 -->  
  12.     <!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id   
  13.         #{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型   
  14.         #{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 -->  
  15.     <!-- 根据id查用户 -->  
  16.     <select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">  
  17.         select * from f_client where id=#{id}  
  18.     </select>  
  19.   
  20.     <!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入   
  21.         ${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 -->  
  22.     <select id="findClientByName" parameterType="java.lang.String"  
  23.         resultType="mybatis.po.FClient">  
  24.         select *from f_client where username like '%${value}%'  
  25.     </select>  
  26.   
  27.     <!-- 添加用户 这里注意 主键返回实现 -->  
  28.     <select id="insertClient" parameterType="mybatis.po.FClient"  
  29.         resultType="java.lang.Integer">  
  30.         insert into  
  31.         f_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)  
  32.         values (#{id},  
  33.         #{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})  
  34.     </select>  
  35.   
  36.     <!-- 删除用户 -->  
  37.     <delete id="deleteClient" parameterType="int">  
  38.         delete from f_client where id=#{id}  
  39.     </delete>  
  40.   
  41.     <!-- 更新用户 -->  
  42.     <update id="updateClient" parameterType="mybatis.po.FClient">  
  43.   
  44.         update f_client set  
  45.         username=#{username},client_certificate_no=#{client_certificate_no},born_date=#{born_date},family_register_address=#{family_register_address},now_address=#{now_address},contact_mode=#{contact_mode},urgency_contact_mode=#{urgency_contact_mode}  
  46.         where id=#{id}  
  47.   
  48.     </update>  
  49.   
  50.   
  51. </mapper>  



 

   (2)mapper接口

               注意接口定义的和Mapper.xml对比下,看看mapper.xml的 规范!!

 

[java] view plain copy
 
  1. package mybatie.mapper;  
  2.   
  3. import java.util.List;  
  4.   
  5. import mybatis.po.FClient;  
  6.   
  7.   
  8. /** 
  9.  * mapper接口 ,对应Clientmapper.xml 
  10.  * 作者:原明卓 
  11.  * 时间:2015年12月21日 上午10:00:00 
  12.  * 描述:TODO 
  13.  */  
  14. public interface ClientMapper {  
  15.       
  16.     public FClient findClientById(int id) throws Exception;  
  17.       
  18.     public void updateClient(FClient f)  throws Exception;  
  19.       
  20.     public void deleteClient(int id) throws Exception;  
  21.   
  22.     public int insertClient(FClient f) throws Exception;  
  23.       
  24.     public List<FClient> findClientByName(String name) throws Exception;  
  25. }  

 

      (3)测试

 

 

[java] view plain copy
 
  1. private SqlSessionFactory sqlfactory;  
  2.   
  3. @Before  
  4. public void setUp() throws Exception {  
  5.     InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");  
  6.     sqlfactory=new SqlSessionFactoryBuilder().build(is);  
  7. }  
  8.   
  9. @Test  
  10. public void testFindClientById() throws Exception {  
  11.     SqlSession session = sqlfactory.openSession();  
  12.     ClientMapper mapper = session.getMapper(ClientMapper.class);  
  13.     FClient fc = mapper.findClientById(1);  
  14.     System.out.println(fc);  
  15.     session.close();  
  16. }  



 

 

4.一些问题

       (1)代理对象内部调用selectOne或 selectList
 如果mapper方法返回单个pojo对象,代理对象内部通过selectOne查询数据库;
 如果mapper方法返回集合对象,代理对象内部通过内部通过selectList查询数据库;
 否则会报错误。
        (2) mapper接口方法参数只能有一个是否影响系统开发
  系统框架中,dao层的代码是否是被业务层公用的,即使mapper接口只有一个参数,可以使用包装
 类型pojo满足不同业务方法需求;
  注意:持久层方法的参数可以包装类型,map,service方法中建议不要使用包装类型,因为不利于
 业务层的可扩展性。

1.背景

   在上篇中我们使用了MyBatis实现简单的增删改查,并没有进行dao层的封装,所以在这里我们进行dao层开发:

   (1)传统的jdbc dao层开发(写dao接口,实现dao接口类)

   (2)mapper代理方法 (只需要写mapper接口类,相当于dao接口类)

     在Mybatis操作的时候,我们使用的是SqlSession 来进行数据库操作,其中SqlSession的使用范围:
     通过SqlSessionFactoryBuilder创建SqlSessionFactory ,而SqlSession通过SqlSessionFactory 创建,所以使用单例模式管理SqlSessionFactory,将来使用mybatis和spring整合后,使用单例模式管理SqlSessionFactory;
      

     SqlSession的作用是:
            1)提供接口,很多操作数据库的方法,如:selectOne ,selectList
  2)线程不安全,在sqlSession实现类中除了有接口中的方法,还有数据域的属性;
  3)最佳应用的场合在方法体内,定义成局部变量使用。

 

2.原始dao开发实现

   (1)dao接口

 

[java] view plain copy
 
  1. package mybatie.dao;  
  2.   
  3. import mybatis.po.FClient;  
  4.   
  5.   
  6. /** 
  7.  * 用户接口 
  8.  * 
  9.  * 作者:原明卓 
  10.  * 时间:2015年12月21日 上午10:00:00 
  11.  * 描述:TODO 
  12.  */  
  13. public interface ClientDao {  
  14.       
  15.     FClient findClientById(int id) throws Exception;  
  16.       
  17.     void updateClient(FClient f)  throws Exception;  
  18.       
  19.     void deleteClient(int id) throws Exception;  
  20.   
  21.     void insertClient(FClient f) throws Exception;  
  22.       
  23. }  

 

    (2)实现dao接口

 

             实现数据库操作的几个方法:

 

[java] view plain copy
 
  1. package mybatie.dao;  
  2.   
  3. import mybatis.po.FClient;  
  4. import oracle.net.aso.s;  
  5.   
  6. import org.apache.ibatis.session.SqlSession;  
  7. import org.apache.ibatis.session.SqlSessionFactory;  
  8.   
  9. public class ClientDaoImp implements ClientDao {  
  10.   
  11.     private SqlSessionFactory sqlSessionFactory;  
  12.   
  13.     public ClientDaoImp(SqlSessionFactory sqlSessionFactory) {  
  14.         this.sqlSessionFactory = sqlSessionFactory;  
  15.     }  
  16.   
  17.     @Override  
  18.     public FClient findClientById(int id) {  
  19.   
  20.         SqlSession sqlSession = sqlSessionFactory.openSession();  
  21.         FClient c = sqlSession.selectOne("test.findClientById", id);  
  22.         sqlSession.close();  
  23.         return c;  
  24.     }  
  25.   
  26.     @Override  
  27.     public void updateClient(FClient f) {  
  28.         SqlSession sqlSession=sqlSessionFactory.openSession();  
  29.         sqlSession.update("test.updateClient",f);  
  30.         sqlSession.commit();  
  31.         sqlSession.close();  
  32.     }  
  33.   
  34.     @Override  
  35.     public void deleteClient(int id) {  
  36.           SqlSession session = sqlSessionFactory.openSession();  
  37.           session.delete("test.deleteClient", id);  
  38.           session.commit();  
  39.           session.close();  
  40.     }  
  41.   
  42.     @Override  
  43.     public void insertClient(FClient f) {  
  44.         SqlSession session = sqlSessionFactory.openSession();  
  45.         session.insert("test.insertClient", f);  
  46.         session.commit();  
  47.         session.close();   
  48.     }  
  49.       
  50.   
  51. }  



 

   (3)测试类

 

[java] view plain copy
 
  1. public class TestClient {  
  2.   
  3.     private SqlSessionFactory sqlSessionFactory;  
  4.   
  5.     @Before  
  6.     public void setUp() throws Exception {  
  7.         InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");  
  8.         sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);  
  9.     }  
  10.   
  11.     @Test  
  12.     public void test() {  
  13.         fail("Not yet implemented");  
  14.     }  
  15.   
  16.     @Test  
  17.     public void findClientById() throws Exception {  
  18.   
  19.         ClientDao clientDao = new ClientDaoImp(sqlSessionFactory);  
  20.         FClient c = clientDao.findClientById(1);  
  21.         System.out.println(c);  
  22.     }  
  23.   
  24. }  

 

    (4)原始的dao层遇到的问题

 

             1)dao接口实现类方法中存在大量的模板方法,设想能否将这些代码提取出来
     2)调用sqlsession方法的时候将statement存在硬编码
     3)调用sqlsession的方法的时候,传入参数为Object 类型,及时传入错误,也不会报错

 

3.使用Mapper代理的方式实现

      基本步骤为 :   

             1)编写mapper.xml映射文件 

             2)编写Mapper接口,相当于dao接口 

             3)mybatis可以自动生成mapper接口的实现类代理对象

    (1)实现Mapper映射文件

              mapper.xml 规范 :
 1)namespace 等于mapper接口地址
 2)mapper.Java 接口中的方法和mapper.xml中的statement 的id一致
 3)mapper.java 接口中的方法的参数和mapper.xml中的statement 的paramterType类型一致
 4)mapper.java 接口中的方法的返回值和mapper.xml中的statement的resultType类型一致
 
总结 :mapper.xml实现的规范,就是对SqlSession接口中的方法进行统一的生成

       比如 :

 

[html] view plain copy
 
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper  
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  5.   
  6. <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 -->  
  7. <!-- 注意:使用mapper代理的方法开发,namespace有特殊的重要作用,namespace为mapper接口的地址 -->  
  8.   
  9. <mapper namespace="mybatie.mapper.ClientMapper">  
  10.   
  11.     <!-- 在映射文件中配置很多的sql语句 -->  
  12.     <!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id   
  13.         #{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型   
  14.         #{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 -->  
  15.     <!-- 根据id查用户 -->  
  16.     <select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">  
  17.         select * from f_client where id=#{id}  
  18.     </select>  
  19.   
  20.     <!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入   
  21.         ${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 -->  
  22.     <select id="findClientByName" parameterType="java.lang.String"  
  23.         resultType="mybatis.po.FClient">  
  24.         select *from f_client where username like '%${value}%'  
  25.     </select>  
  26.   
  27.     <!-- 添加用户 这里注意 主键返回实现 -->  
  28.     <select id="insertClient" parameterType="mybatis.po.FClient"  
  29.         resultType="java.lang.Integer">  
  30.         insert into  
  31.         f_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)  
  32.         values (#{id},  
  33.         #{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})  
  34.     </select>  
  35.   
  36.     <!-- 删除用户 -->  
  37.     <delete id="deleteClient" parameterType="int">  
  38.         delete from f_client where id=#{id}  
  39.     </delete>  
  40.   
  41.     <!-- 更新用户 -->  
  42.     <update id="updateClient" parameterType="mybatis.po.FClient">  
  43.   
  44.         update f_client set  
  45.         username=#{username},client_certificate_no=#{client_certificate_no},born_date=#{born_date},family_register_address=#{family_register_address},now_address=#{now_address},contact_mode=#{contact_mode},urgency_contact_mode=#{urgency_contact_mode}  
  46.         where id=#{id}  
  47.   
  48.     </update>  
  49.   
  50.   
  51. </mapper>  



 

   (2)mapper接口

               注意接口定义的和Mapper.xml对比下,看看mapper.xml的 规范!!

 

[java] view plain copy
 
  1. package mybatie.mapper;  
  2.   
  3. import java.util.List;  
  4.   
  5. import mybatis.po.FClient;  
  6.   
  7.   
  8. /** 
  9.  * mapper接口 ,对应Clientmapper.xml 
  10.  * 作者:原明卓 
  11.  * 时间:2015年12月21日 上午10:00:00 
  12.  * 描述:TODO 
  13.  */  
  14. public interface ClientMapper {  
  15.       
  16.     public FClient findClientById(int id) throws Exception;  
  17.       
  18.     public void updateClient(FClient f)  throws Exception;  
  19.       
  20.     public void deleteClient(int id) throws Exception;  
  21.   
  22.     public int insertClient(FClient f) throws Exception;  
  23.       
  24.     public List<FClient> findClientByName(String name) throws Exception;  
  25. }  

 

      (3)测试

 

 

[java] view plain copy
 
  1. private SqlSessionFactory sqlfactory;  
  2.   
  3. @Before  
  4. public void setUp() throws Exception {  
  5.     InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");  
  6.     sqlfactory=new SqlSessionFactoryBuilder().build(is);  
  7. }  
  8.   
  9. @Test  
  10. public void testFindClientById() throws Exception {  
  11.     SqlSession session = sqlfactory.openSession();  
  12.     ClientMapper mapper = session.getMapper(ClientMapper.class);  
  13.     FClient fc = mapper.findClientById(1);  
  14.     System.out.println(fc);  
  15.     session.close();  
  16. }  



 

 

4.一些问题

       (1)代理对象内部调用selectOne或 selectList
 如果mapper方法返回单个pojo对象,代理对象内部通过selectOne查询数据库;
 如果mapper方法返回集合对象,代理对象内部通过内部通过selectList查询数据库;
 否则会报错误。
        (2) mapper接口方法参数只能有一个是否影响系统开发
  系统框架中,dao层的代码是否是被业务层公用的,即使mapper接口只有一个参数,可以使用包装
 类型pojo满足不同业务方法需求;
  注意:持久层方法的参数可以包装类型,map,service方法中建议不要使用包装类型,因为不利于
 业务层的可扩展性。

原文地址:https://www.cnblogs.com/wangf-keep/p/6425633.html