你的位置:首页 > Java教程

[Java教程]Mybatis学习笔记(三) 之Dao开发

使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法和Mapper接口开发方法,常用还是Mapper接口开发。

SqlSession的使用范围

public class test1 {  private static SqlSessionFactory sqlSessionFactory;  private static Reader reader;   //创建会话工厂,传入mybatis的配置文件信息  static{    try{    	//得到配置文件流      reader = Resources.getResourceAsReader("Configuration.

想要通过mabatis对数据库操作,除了要各种配置之外,最终在测试的时候,需要创建特定对象,上图示例:

1、SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

2、SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory

3、SqlSession

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。

SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等。通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建。

结论:

每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。

  	//通过工厂得到sqlsession    SqlSession session = sqlSessionFactory.openSession();    try {    } finally {      session.close();    }

 原始Dao开发方式

程序员需要编写DAO和DAO的实现类。需要向DAO实现类中注入SqlSessionFactory,在方法体内通过SqlSessionFactory来创建SqlSession。

1、定义Dao接口

public interface UserDAO{  //根据本id查询用户  User findUserById(int id) throws Exception;    //添加用户  void insertUser(User user) throws Exception;    //根据id删除用户  void deleteUser(int id) throws Exception;}

2、Dao实现类

DAO实现类/*** @ClassName: UserDAOImpl * @Description: DAO实现类(注意:SqlSession是非线程安全的,故不能声明为全局的) */public class UserDAOImpl implements UserDAO {  SqlSessionFactory sqlSessionFactory;  /**   * 向DAO实现类中注入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();  }}

3、新建一个源代码目录命名为test,在UserDAOImpl类中鼠标右键新建一个Junit Test Case,更换源代码目录为test并勾选我们需要测试的方法:

public class UserDAOImplTest {  private SqlSessionFactory sqlSessionFactory;    /**   * 此方法在执行测试之前执行,得到一个SqlSessionFactory   */  @Before  public void setUp() throws Exception {        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("SqlMapConfig.

原始DAO开发中存在的问题

  • DAO的接口实现类中存在大量的模板方法,设想:可以将重复的代码提取出来。

  • 在SqlSession的方法时将Statement的id硬编码在你DAO的实现类中。

  • 调用sqlSession的相关方法传入参数是泛型,即使传入错误的参数,在编译阶段也不会报错,不利于程序员开发。

Mapper动态代理方式

实现原理

Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper接口开发需要遵循以下规范:Mapper可以自动生成Mapper接口实现类代理对象。

1、 Mapper.文件中的namespace与mapper接口的类路径相同。

2、  Mapper接口方法名和Mapper.中定义的每个statement的id相同

3、 Mapper接口方法的输入参数类型和mapper.中定义的每个sql 的parameterType的类型相同

4、 Mapper接口方法的输出参数类型和mapper.中定义的每个sql的resultType的类型相同

1、UserMapper.
<?

2、UserMapper.java类

package com.yihaomen.mybatis.dao;import java.util.List;import com.yihaomen.mybatis.model.Article;import com.yihaomen.mybatis.model.User;//注意:接口名字必须与 

完成前面2步之后不要忘了在映射文件SqlMapConfig.

<!-- 配置映射文件 --><mappers>  <mapper resource="sqlmap/User.

3、针对UserMapper接口测试

package com.yihaomen.mybatis.ui;import java.io.Reader;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import com.yihaomen.mybatis.dao.IUserOperation;import com.yihaomen.mybatis.model.User;public class Test {  private static SqlSessionFactory sqlSessionFactory;  private static Reader reader;   //创建会话工厂,传入mybatis的配置文件信息  static{    try{    	//得到配置文件流      reader = Resources.getResourceAsReader("Configuration.
  • 我们比较疑问的就是我们在UserMapper.selectOne()或者selectList(),代理对象内部会自动进行判断是否是单独的POJO选用合适的方法。

  • Mapper接口中方法的参数只有一个是否会影响系统的维护?DAO层的代码是被业务层公用的,即使Mapper接口的参数只有一个我们也可以使用包装的POJO来满足系统需求。

  • 注意:持久层中方法的参数中可以使用包装类型,但是Service层中不建议使用包装类型(不利于业务层的拓展维护)。