您的位置:首页 > 移动开发

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

2015-12-21 14:43 381 查看

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;
}

@Override
public FClient findClientById(int id) {

SqlSession sqlSession = sqlSessionFactory.openSession();
FClient c = sqlSession.selectOne("test.findClientById", id);
sqlSession.close();
return c;
}

@Override
public void updateClient(FClient f) {
SqlSession sqlSession=sqlSessionFactory.openSession();
sqlSession.update("test.updateClient",f);
sqlSession.commit();
sqlSession.close();
}

@Override
public void deleteClient(int id) {
SqlSession session = sqlSessionFactory.openSession();
session.delete("test.deleteClient", id);
session.commit();
session.close();
}

@Override
public void insertClient(FClient f) {
SqlSession session = sqlSessionFactory.openSession();
session.insert("test.insertClient", f);
session.commit();
session.close();
}

}


   (3)测试类

public class TestClient {

private SqlSessionFactory sqlSessionFactory;

@Before
public void setUp() throws Exception {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}

@Test
public void test() {
fail("Not yet implemented");
}

@Test
public 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 mapper
PUBLIC "-//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 into
f_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 set
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}
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;

@Before
public void setUp() throws Exception {
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
sqlfactory=new SqlSessionFactoryBuilder().build(is);
}

@Test
public 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方法中建议不要使用包装类型,因为不利于
 业务层的可扩展性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dao sqlsession mapper