前言
因为 MyBatis
的易上手性和可控性,使得它成为了 ORM
框架中的首选。近日新起了一个项目,所以重新搭建了一下 Spring-mybatis
, 下面是搭建笔记和从 Spring-mybatis
源码分析其如何使用 Java动态代理
,希望对大家有帮助。
Spring 集成 Mybatis
Spring
集成 Mybatis
的方式有很多种,大家耳熟能详的 xml
配置方式或者本文的采用的方式:
首先需要添加 MyBatis
的和 MyBatis-Spring
的依赖,本文使用的 Spring-mybatis
版本是1.3.1。在 mvnrepository
里面我们可以找到当前 Spring-mybatis
依赖的 spring
和 mybatis
版本,最好是选择匹配的版本以避免处理不必要的兼容性问题。因为 MyBatis-Spring
中对 mybatis
的依赖选择了 provided
模式,所以我们不得不额外添加 mybatis
依赖,依赖配置如下。
-
<dependency>
-
<groupId>org.mybatis</groupId>
-
<artifactId>mybatis-spring</artifactId>
-
<version>1.3.1</version>
-
</dependency>
-
<dependency>
-
<groupId>org.mybatis</groupId>
-
<artifactId>mybatis</artifactId>
-
<version>3.4.1</version>
-
</dependency>
接下来会我们要创建工厂bean,放置下面的代码在 Spring 的 XML 配置文件中:
-
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
-
<property name="dataSource" ref="dataSource" />
-
</bean>
这个工厂需要一个 DataSource
,就是我们熟知的数据源了。这里我们选择了阿里的 Druid
,同样我们需要引入两个配置
-
<dependency>
-
<groupId>mysql</groupId>
-
<artifactId>mysql-connector-java</artifactId>
-
<version>5.1.41</version>
-
</dependency>
-
<dependency>
-
<groupId>com.alibaba</groupId>
-
<artifactId>druid</artifactId>
-
<version>1.1.2</version>
-
</dependency>
添加 Spring
配置如下
-
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
-
<!-- 基本属性 url、user、password -->
-
<property name="url">
-
<value><![CDATA[${db.url}]]></value>
-
</property>
-
<property name="username" value="${db.username}"/>
-
<property name="password" value="${db.password}"/>
-
<!-- 省略其他配置 -->
-
</bean>
接下来我们要编写数据库访问对象,大多数人会把它叫做 DAO
或者 Repository
,在这里其被称为
Mapper
,也是因为它的实现方式所决定。要注意的是所指定的映射器类必须是一个接口,而不是具体的实现类。这便因为 Mybatis
的内部实现使用的是 Java动态代理
,而 Java动态代理
只支持接口,关于 动态代理
我们下文有更详细的描述。
-
public interface UserMapper {
-
@Select("SELECT * FROM users WHERE id = #{userId}")
-
User getUser(@Param("userId") String userId);
-
}
接下来可以使用 MapperFactoryBean
,像下面这样来把接口加入到 Spring
中,这样就把 UserMapper
和 SessionFactory
关联到一起了,原来使用 xml
配置的时候还需要Dao继承 SqlSessionDaoSupport
才能注入 SessionFactory
,这种方式直接通过 Java动态代理
把 SqlSessionFactory
代理给了 UserMapper
,使得我们直接使用 UserMapper
即可。配置如下。
-
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
-
<property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
-
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
-
</bean>
这样我们已经完成了90%,就差调用了,前提是你 Spring
环境是OK的。调用 MyBatis
数据方法现在只需一行代码:
-
public class FooServiceImpl implements FooService {
-
-
private UserMapper userMapper;
-
-
public void setUserMapper(UserMapper userMapper) {
-
this.userMapper = userMapper;
-
}
-
-
public User doSomeBusinessStuff(String userId) {
-
return this.userMapper.getUser(userId);
-
}
那么问题又来了,每次写一个DAO都需要为其写一个 Bean
配置,那不是累死?于是我们又寻找另一种方案,代替手动声明 *Mapper
。 MapperScannerConfigurer
的出现解决了这个问题, 它会根据你配置的包路径自动的扫描类文件并自动将它们创建成 MapperFactoryBean
,可以在 Spring 的配置中添加如下代码:
-
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
-
<property name="basePackage" v