初识Mybatis-Spring

来源:互联网 发布:翻页相册制作软件 编辑:程序博客网 时间:2024/05/01 23:05

注:本文大量参考Mybatis-Spring文档http://mybatis.github.io/spring/zh/

排版不规范,并且主要是供自己参考所用,所以文章中可能有些批注,有些发现的问题。后面可能有相应的解释。仅供参考。


 在不与spring整合的时候,一般会生成一个SqlSessionFactory,然后从中获得SqlSession,类似于hibernatesession,封装了一个jdbc连接或者说是preparedstatement可以直接对数据库操作。

例如:

SqlSession session = sqlSessionFactory.openSession();
try {
  Blog blog = (Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog",101);
} finally {
  session.close();
}

 

来自<http://mybatis.github.io/mybatis-3/zh/getting-started.html>

但这是老版本的做法。更现代的做法是:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper =session.getMapper(BlogMapper.class);
  Blog blog =mapper.selectBlog(101);
} finally {
  session.close();
}

 

来自<http://mybatis.github.io/mybatis-3/zh/getting-started.html>

与上面两种写法相对应的:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog"resultType="Blog">
    select * from Blog where id =#{id}
  </select>
</mapper>

 

来自<http://mybatis.github.io/mybatis-3/zh/getting-started.html>

 

差别在于:

Blog blog = (Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

 

BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);

 

来自<http://mybatis.github.io/mybatis-3/zh/getting-started.html>

 

 

两者都使用了selectBlog(int i);方法。从上面xml文件可以看出来这个方法对应着xml中的一个语句的id

 

对于像 BlogMapper 这样的映射器类(Mapper class)来说,还有另一招来处理。它们的映射的语句可以不需要用 XML来做,取而代之的是可以使用 Java 注解。比如,上面的 XML 示例可被替换如下:

package org.mybatis.example;
public interface BlogMapper {
  @Select("SELECT * FROM blog WHEREid = #{id}")
  Blog selectBlog(int id);
}

 

来自<http://mybatis.github.io/mybatis-3/zh/getting-started.html>

 

注意 ****Maper都是采用的接口,而非实体类。为其指定sql语句时,可以通过两种方法:通过注解(简单SQL可行)或者是通过xml文件。

 

 

 

Mybatis Spring中一些常用的Bean

SqlSessionFactoryBean

org.Mybatis.spring.SqlSessionFactoryBean    需要一个datasource

如果映射器xml文件不在映射器类相同路径下,那么需要配置。有两种选择:1.手动在mybatisxml配置文件中使用<mappers>部分来指定类路径。2.使用beanmapperLocations属性

案例:

<bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">
  <propertyname="dataSource" ref="dataSource" />
  <propertyname="mapperLocations"value="classpath*:sample/config/mappers/**/*.xml"/>
</bean>

 

来自<http://mybatis.github.io/spring/zh/factorybean.html>

 

 

MapperFactoryBean

org.mybatis.spring.mapper.MapperFactorybean需要mapperInterface(***Mapper),需要sqlSessionFactory

一旦配置好后,可以将其注入到任意的由Spring管理的bean中,一般是将其注入到service对象中。但是貌似要配置好多,需要用到多少个domain对象,就得创建多少个mapper

案例:

public class FooServiceImpl implements FooService {

private UserMapper userMapper;

public void setUserMapper(UserMapper userMapper) {
  this.userMapper = userMapper;
}

public User doSomeBusinessStuff(String userId) {
  returnthis.userMapper.getUser(userId);
}

 

来自<http://mybatis.github.io/spring/zh/getting-started.html>

SqlSession

在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session之后,你可以使用它来执行映射语句,提交或回滚连接,最后,当不再需要它的时 候, 你可以关闭 session。 使用 MyBatis-Spring 之后,你不再需要直接使用 SqlSessionFactory 了,因为你的 bean 可以通过一个线程安全的 SqlSession 来注入,基于 Spring的事务配置 来自动提交,回滚,关闭 session。

 

注意通常不必直接使用 SqlSession。 在大多数情况下 MapperFactoryBean, 将会在 bean中注入所需要的映射器。下一章节中的 MapperFactoryBean会解释这个细节。

 

来自<http://mybatis.github.io/spring/zh/sqlsession.html>

 

SqlSessionTemplate

此类负责管理MybatisSqlSession。是线程安全的,可以被多个DAO共享。

当调用 SQL 方法时, 包含从映射器 getMapper()方法返回的方法, SqlSessionTemplate 将会保证使用的SqlSession 是和当前 Spring 的事务相关的。此外,它管理 session 的生命 周期,包含必要的关闭,提交或回滚操作。

 

SqlSessionTemplate 实现了 SqlSession接口,这就是说,在代码中无需对 MyBatis 的 SqlSession 进行替换。 SqlSessionTemplate 通常是被用来替代默认的MyBatis 实现的 DefaultSqlSession , 因为模板可以参与到 Spring 的事务中并且被多个注入的映射器类所使用时也是线程安全的。相同应用程序中两个类(应该指SqlSessionTemplate,DefaultSqlSession)之间的转换可能会引起数据一致性的问题。

 

来自<http://mybatis.github.io/spring/zh/sqlsession.html>

 

 

 

SqlSessionTemplate 对象可以使用 SqlSessionFactory 作为构造方法的参数来创建。

<bean id="sqlSession"class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0"ref="sqlSessionFactory" />
</bean>

 

来自<http://mybatis.github.io/spring/zh/sqlsession.html>

这样这个bean就可以注入到DAObean中了。注意,dao本身是个接口,应该注入到实现中。(这种做法类似于hibernate和传统jdbc程序分层结构,但后面讲可能不用写实现)

注意到文档写的还是有点乱,Dao的实现可能就是Mapper

SqlSessionTemplate有一个使用ExecutorType作为参数的构造方法。用来创建对象,例如一个批量SqlSession

例如:

<bean id="sqlSession"class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg index="0"ref="sqlSessionFactory" />
  <constructor-arg index="1"value="BATCH" />
</bean>

 

现在你所有的语句可以批量操作了,下面的语句就可以在 DAO中使用了。

public void insertUsers(User[] users) {
   for (User user : users) {
    sqlSession.insert("org.mybatis.spring.sample.mapper.UserMapper.insertUser",user);
   }
 }

(难道说没有加这个属性之前不能用这个语句?待测试。)

来自<http://mybatis.github.io/spring/zh/sqlsession.html>

 

SqlSessionDaoSupport

一个抽象的支持类,调用getSqlSession()方法得到一个SqlSessionTemplate

SqlSessionDaoSupport 需要一个 sqlSessionFactory 或 sqlSessionTemplate 属性来设 置

 

来自<http://mybatis.github.io/spring/zh/sqlsession.html>

 

 

MapperFactoryBean

数据映射器接口可以按照如下做法加入到 Spring:

<bean id="userMapper"class="org.mybatis.spring.mapper.MapperFactoryBean">
  <propertyname="mapperInterface"value="org.mybatis.spring.sample.mapper.UserMapper" />
  <propertyname="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

看来对于一些按类型注入的自动注入要小心使用,最好加上名称限制。目测每一个mapper都需要一个这样的Bean啊。

其实这里的UserMapper就相当于hibernate中的UserDao(接口)

来自<http://mybatis.github.io/spring/zh/mappers.html>

 

如果UserMapper有一个对应的Mybatisxml映射器文件,如果xml文件在类路径的位置和映射器接口相同时,他会被MapperFactoryBean自动解析,没有必要再Mybatis配置文件中去制定映射器。除非接口与xml映射文件不在同一路径下。参考SqlSessionFactoryBeanconfigLocation属性(github的一份源码中看到的是mapperLocations,value="classpath:rml/mapping/*.xml")

 

 

 

注入映射器

MapperFactoryBean

       上面的代码中都是手工使用SqlSessionDaoSupport或者SqlSessionTemplate编写数据访问对象(Dao)的实现,Mybatis-Spring提供了一个动态代理的实现:MapperFactoryBean。这个类可以直接注射数据访问器接口道Service层的bean中,不需要编写DAO实现的代码,由Mybatis-Spring创建代理。

 

       MapperFactoryBean创建的代理控制打开和关闭Session,并且将异常包装到SpringDataAccessException异常中,提供准确详细干净的异常信息。此外,如果需要参与到一个已经存在活动事物中,代理将会开启一个新的Spring事物。

 

 

MapperScannerConfigurer

为了解决上面的疑惑(目测每一个mapper都需要一个这样的Bean啊。)这样确实太麻烦。所以:

没有必要再Springxml配置文件中注册所有的映射器(Mapper)

<bean id="userMapper"class="org.mybatis.spring.mapper.MapperFactoryBean">
  <propertyname="mapperInterface"value="org.mybatis.spring.sample.mapper.UserMapper" />
  <propertyname="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

现在只需要一个MapperScannerConfigurer,他将会查找类路径下的映射器并自动为他们创建成MapperFactoryBean。例如:

<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <propertyname="basePackage" value="org.mybatis.spring.sample.mapper"/>
</bean>

 

来自<http://mybatis.github.io/spring/zh/mappers.html>

       basePackage属性是为了让你为映射器接口文件设置基本的包路径。可以使用分啊后或者都好作为分隔符设置多于一个的包路径,每个映射器(接口)将会在指定的包路径中被递归的搜索。

MapperScannerConfigurer属性不支持使用了PropertyPlaceholderConfigurer的属性替换

         没有必要去指定SqlSessionFactory或者SqlSessionTemplate,因为MapperScannerConfigurer将会创建MapperFactoryBean,之后自动装配。但是如果使用了一个以上的datasource,那么自动装配可能会失效

这种情况下 ,你可以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName属性来设置正确的 bean 名 称来使用。这就是它如何来配置的,注意 bean 的名称是必须的,而不是 bean 的引用,因 此,value属性在这里替代通常的 ref:

<property name="sqlSessionFactoryBeanName"value="sqlSessionFactory" />

 

来自<http://mybatis.github.io/spring/zh/mappers.html>

MapperScannerConfigurer 支 持 过 滤 由 指 定 的 创 建 接 口 或 注 解 创 建 映 射 器 。annotationClass 属性指定了要寻找的注解名称。 markerInterface 属性指定了要寻找的父接口。如果两者都被指定了,加入到接口中的映射器会匹配两种标准。默认情况下,这两个 属性都是 null,所以在基包中给定的所有接口可以作为映射器加载。

 

被发现的映射器将会使用 Spring 对自动侦测组件(参考 Spring 手册的 3.14.4)默认的命名策略来命名。也就是说,如果没有发现注解,它就会使用映射器的非大写的非完全限定类 名。但是如果发现了@Component 或 JSR-330 的@Named注解,它会获取名称。注意你可以 配 置 到 org.springframework.stereotype.Component ,javax.inject.Named(如果你使用 JSE 6 的话)或你自己的注解(肯定是自我注解)中,这 样注解将会用作生成器和名称提供器。

 

来自<http://mybatis.github.io/spring/zh/mappers.html>

 


0 0
原创粉丝点击