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

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方法中建议不要使用包装类型,因为不利于
 业务层的可扩展性。


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值