MyBatis-Spring的使用

本文是 MyBatis-Spring 官方文档的阅读笔记,方便后续查阅。

使用说明

记录使用过程中的一些配置及说明

Maven 依赖

项目中添加以下 pom 依赖即可

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>

入门配置

仅用于学习研究,生产上一般不这么使用

接口定义

Mapper 接口,也就是 DAO 接口,定义了数据的访问方式

1
2
3
public interface UserMapper {
User getUser(@Param("userId") String userId);
}

MyBatis 支持将 sql 语句以注解的形式添加到 Mapper 接口的方法上

1
2
3
4
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{userId}")
User getUser(@Param("userId") String userId);
}

有了 Mapper 之后,数据操作就是下面这个样子

1
2
3
4
5
6
7
8
9
10
11
12
public class FooServiceImpl implements FooService {

private final UserMapper userMapper;

public FooServiceImpl(UserMapper userMapper) {
this.userMapper = userMapper;
}

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

这里的问题是:我们只定义了 Mapper 接口,并没有对应的实现类,无法完成数据库操作。

这需要有一个代理类,它实现了我们的 Mapper 接口,并且代理了接口方法,方法的主要工作是完成对应的数据库操作。

要实现这样一个代理类,并不需要我们写太多代码,MyBatis-Spring 提供了很方便的实现方法

Mapper 配置

MyBatis-Spring 提供了 SqlSessionTemplate 类,用于创建 Mapper 接口的代理类

1
sqlSessionTemplate.getMapper(UserMapper.class)

因此,创建 Mapper 接口代理的代码就是下面这个样子:先创建 SqlSessionTemplate 实例,然后调用其 getMapper 方法获取指定 Mapper 接口的代理。

1
2
3
4
5
@Bean
public UserMapper userMapper() throws Exception {
SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory());
return sqlSessionTemplate.getMapper(UserMapper.class);
}

如果你使用的不是 java bean 的方式,而是用的 xml 配置,那也没问题,可以这样配置

1
2
3
4
<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>

可以看到,这两种方式都需要先拿到 sqlSessionFactory 实例。

关于后一种方式,MapperFactoryBean 是基于 SqlSessionTemplate 实现的,它的 getObject 方法会先获取到 sqlSessionTemplate 实例,然后调用其 getMapper 方法

1
return getSqlSession().getMapper(this.mapperInterface);

SqlSessionFactory 配置

我们需要创建 SqlSessionFactory 实例,这可以通过 SqlSessionFactoryBean 来实现。SqlSessionFactoryBean 是一个 FactoryBean,它专门用来创建 SqlSessionFactory,使用方法如下

1
2
3
4
5
6
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}

它需要设置 DataSource,然后就可以创建 SqlSessionFactory

如果使用的是 xml 方式,只需要将上述 java bean 方式转换下即可

1
2
3
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

DataSource 配置

DataSource 用于管理数据库连接,它的实现方式有多种,视具体情况而定,比如有 c3p0、druid、commons-dbcp2 等。以 commons-dbcp2 为例,它的配置格式如下

1
2
3
4
5
6
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

进阶配置

正式的项目里,Mapper 接口通常有多个,如果每一个都配置下 Spring Bean,光这部分工作量就很多。因此 MaBatis-Spring 还提供了按包路径扫描的方式。

Mapper 扫描配置

通过 MapperScannerConfigurer 配置要扫描的 Mapper 接口包路径,比如要扫描 com.gorden5566.springmvc.dao 路径下的所有 Mapper 接口,只需要按如下方式进行配置即可

1
2
3
4
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.gorden5566.springmvc.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

如果你用的是注解的方式,则按如下方式配置

1
@MapperScan(basePackages = "com.gorden5566.springmvc.dao", sqlSessionFactoryRef = "sqlSessionFactory")

SqlSessionFactory 配置

前面说过使用 SqlSessionFactoryBean 配置 SqlSessionFactory,除了需要配置 dataSource 属性外,通常还会配置它的 configLocation 属性和 mapperLocations 属性,如下所示:

1
2
3
4
5
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>
</bean>

其中 configLocation 用于指定 MaBatis 的配置文件逻辑,如下是一个示例,表示打开 MyBatis 的缓存

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>

mapperLocations 用于指定 mapper 配置文件的路径。前面提到的 Mapper 接口中使用注解配置对应的 sql 语句

1
2
3
4
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{userId}")
User getUser(@Param("userId") String userId);
}

当 sql 比较复杂的时候代码会很混乱,sql 较多的话也会很难维护,通常是将 mapper 接口和对应的 sql 分开管理,sql 单独写到配置文件中,如下所示

1
2
3
4
5
6
7
8
<?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" >
<mapper namespace="com.gorden5566.springmvc.dao">
<update id="getUser">
SELECT * FROM users
WHERE id = #{userId}
</update>
</mapper>

这样对应的 Mapper 接口定义就更简洁清晰

1
2
3
public interface UserMapper {
User getUser(@Param("userId") String userId);
}

参考

http://mybatis.org/spring/zh/index.html