Mybatis - Mybatis 增删改查之dao层实现

来源:互联网 发布:个性签名生成器软件 编辑:程序博客网 时间:2024/05/22 16:21

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接口

package mybatie.dao;import mybatis.po.FClient;/** * 用户接口 * * 作者:原明卓 * 时间:2015年12月21日 上午10:00:00 * 描述:TODO */public interface ClientDao {FClient findClientById(int id) throws Exception;void updateClient(FClient f)  throws Exception;void deleteClient(int id) throws Exception;void insertClient(FClient f) throws Exception;}

    (2)实现dao接口

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

package mybatie.dao;import mybatis.po.FClient;import oracle.net.aso.s;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;public class ClientDaoImp implements ClientDao {private SqlSessionFactory sqlSessionFactory;public ClientDaoImp(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}@Overridepublic FClient findClientById(int id) {SqlSession sqlSession = sqlSessionFactory.openSession();FClient c = sqlSession.selectOne("test.findClientById", id);sqlSession.close();return c;}@Overridepublic void updateClient(FClient f) {SqlSession sqlSession=sqlSessionFactory.openSession();sqlSession.update("test.updateClient",f);        sqlSession.commit();        sqlSession.close();}@Overridepublic void deleteClient(int id) {          SqlSession session = sqlSessionFactory.openSession();          session.delete("test.deleteClient", id);          session.commit();          session.close();}@Overridepublic void insertClient(FClient f) {    SqlSession session = sqlSessionFactory.openSession();        session.insert("test.insertClient", f);        session.commit();        session.close(); }}


   (3)测试类

public class TestClient {private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUp() throws Exception {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);}@Testpublic void test() {fail("Not yet implemented");}@Testpublic void findClientById() throws Exception {ClientDao clientDao = new ClientDaoImp(sqlSessionFactory);FClient c = clientDao.findClientById(1);System.out.println(c);}}

    (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接口中的方法进行统一的生成

       比如 :

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 --><!-- 注意:使用mapper代理的方法开发,namespace有特殊的重要作用,namespace为mapper接口的地址 --><mapper namespace="mybatie.mapper.ClientMapper"><!-- 在映射文件中配置很多的sql语句 --><!-- 通过select 执行数据库查询 id:表示映射文件的sql, 将sql语句封装到mappedStatement对象中,所以将id称为statement的id #{}: 表示一个占位符,相当于jdbc中的? parameterType : 指定参数类型,比如指定为int #{id} : 其中的id表示接入输入的参数,参数名称就是id,如果输入的参数是简单类型 #{}中参数名可以任意,可以value或其他名称; resultType :指定sql输出的结果的映射java对象类型,select指定的resultType表示将单条记录映射成java对象 --><!-- 根据id查用户 --><select id="findClientById" parameterType="int" resultType="mybatis.po.FClient">select * from f_client where id=#{id}</select><!-- 根据用户名模糊查询 resultType :指定的单条记录所映射的java对象类型 #{} 表示占位符 ${}:表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,使用${}拼接,引起sql注入 ${value} :接入输入参数的内容,如果传入类型是简单类型,${}简单的 --><select id="findClientByName" parameterType="java.lang.String"resultType="mybatis.po.FClient">select *from f_client where username like '%${value}%'</select><!-- 添加用户 这里注意 主键返回实现 --><select id="insertClient" parameterType="mybatis.po.FClient"resultType="java.lang.Integer">insert intof_client(id,username,client_certificate_no,born_date,family_register_address,now_address,contact_mode,urgency_contact_mode,create_date)values (#{id},#{username},#{client_certificate_no},#{born_date},#{family_register_address},#{now_address},#{contact_mode},#{urgency_contact_mode},#{create_data})</select><!-- 删除用户 --><delete id="deleteClient" parameterType="int">delete from f_client where id=#{id}</delete>    <!-- 更新用户 --><update id="updateClient" parameterType="mybatis.po.FClient">update f_client setusername=#{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}where id=#{id}</update></mapper>


   (2)mapper接口

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

package mybatie.mapper;import java.util.List;import mybatis.po.FClient;/** * mapper接口 ,对应Clientmapper.xml * 作者:原明卓 * 时间:2015年12月21日 上午10:00:00 * 描述:TODO */public interface ClientMapper {public FClient findClientById(int id) throws Exception;public void updateClient(FClient f)  throws Exception;public void deleteClient(int id) throws Exception;public int insertClient(FClient f) throws Exception;public List<FClient> findClientByName(String name) throws Exception;}

      (3)测试

private SqlSessionFactory sqlfactory;@Beforepublic void setUp() throws Exception {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");sqlfactory=new SqlSessionFactoryBuilder().build(is);}@Testpublic void testFindClientById() throws Exception {SqlSession session = sqlfactory.openSession();ClientMapper mapper = session.getMapper(ClientMapper.class);FClient fc = mapper.findClientById(1);System.out.println(fc);session.close();}


4.一些问题

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


0 0
原创粉丝点击