前言
目前大部分项目中运用MyBatis均与Spring有关,尤其是Spring Boot大行其道,普通程序员基本上可以无缝的完成一个简单的CRUD项目。通过前面对于MyBatis 源码的学习,我已经对其了(一)如(脸)指(懵)掌(逼),本章我们来玩玩MyBatis与Spring的结合以及它们的融合原理。
一、什么是Mybatis-Spring
一句话:将 MyBatis 代码无缝地整合到 Spring 中。集成过程中的增强处理主要体现在以下几个方面:
- Spring 将会加载必要的 MyBatis 工厂类和 session 类
- 提供一个简单的方式来注入 MyBatis 数据映射器和 SqlSession 到业务层的 bean 中
- 方便集成Spring事务
- 翻译 MyBatis 的异常到 Spring 的 DataAccessException 异常(数据访问异常)中
二、关键配置类
1.SqlSessionFactoryBean
SqlSessionFactoryBean作用:用于创建SqlSessionFactory。关键参数有: - dataSource :必填。用于配置数据源,必须通过这个属性配置数据源。
- mapperLocations : 配置 SqlSessionFactoryBean 扫描*mapper.xml映射文件的路径。
- configLocation :用于配置mybatis-config.xml的路径,除了数据源外,对MyBatis的各种配直仍然可以通过这种方式进行,并且配置MyBatis settings 时只能使用这种方式。但配置文件中任意环境,数据源和 MyBatis 的事务管理器都会被忽略;
- typeAliasesPackage : 配置包中类的别名,配置后,包中的类在 XML 映射文件中使用时可以省略包名部分,直接使用类名。这个配置不支持Ant风格的路径,当需要配置多个包路径时可以使用分号或逗号进行分隔.
2.MapperScannerConfigurer
作用:自动扫描所有的 Mapper 接口,使用时可以直接注入接口。
关键参数: - basePackage :用于配置基本的包路径。可以使用分号或逗号作为分隔符设置多于一个的包路径,每个映射器将会在指定的包路径中递归地被搜索到 。
- annotationClass :用于过滤被扫描的接口,如果设置了该属性,那么 MyBatis 的接口只有包含该注解才会被扫描进去。
三、MyBatis与Spring融合实战
1.依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.3</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
其中spring.version为4.3.3.RELEASE。
2.Spring配置文件
本项目中的spring配置文件名为applicationContext.xml,主要用于配置:
- 数据源
- sqlSessionFactory
- MapperScannerConfigurer
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true" />
<context:component-scan base-package="com.*"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="driverClassName" value="${jdbc_driver}" />
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat" />
</bean>
<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.enjoylearning.mybatis.entity" />
<property name="mapperLocations" value="classpath:sqlmapper/*.xml" />
</bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.enjoylearning.mybatis.mapper" />
</bean>
<!-- (事务管理)transaction manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
<qualifier value="transactionManager" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
3.Mybatis配置文件
文件名为mybatis-config.xml,注意该文件除了settings必须配置在里面外,其他都可以在spring配置文件中配置。
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<!-- 别名定义 -->
<typeAliases>
<package name="com.enjoylearning.mybatis.entity"/>
</typeAliases>
4.mapper
还是以UserInfoMapper.xml为例,文件内容如下:
<?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.enjoylearning.mybatis.mapper.UserInfoMapper">
<resultMap id="BaseResultMap" type="com.enjoylearning.mybatis.entity.UserInfo">
<id column="id" property="id" jdbcType="VARCHAR"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/>
<result column="openid" property="openid" jdbcType="VARCHAR"/>
<result column="role" property="role" jdbcType="BIT"/>
<result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id, username, password, openid, role, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String">
select
<include refid="Base_Column_List"/>
from user_info
where id = #{id,jdbcType=VARCHAR}
</select>
</mapper>
对应dao:
public interface UserInfoMapper {
UserInfo selectByPrimaryKey(String id);
}
po:
public class UserInfo {
private String id;
private String username;
private String password;
private String openid;
private Boolean role;
private Date createTime;
private Date updateTime;
//省略getter、setter
}
5.测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MybatisSpringTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
public void test_selectByPrimaryKey() {
UserInfo userInfo= userInfoMapper.selectByPrimaryKey(1);
System.out.println(userInfo.toString());
}
}
四、Mybatis与SpringBoot融合实战
1.依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<!-- 单元测试相关依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.18</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.application.yml
#DataSource config 配置数据源信息
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springcloudsell?useUnicode=true&characterEncoding=utf-8
username: root
password: root
# 配置MyBatis的配置文件地址和MyBatis的映射文件地址
mybatis:
mapper-locations: classpath*:sqlmapper/*.xml
configuration:
# 关闭二级缓存
cache-enabled: false
map-underscore-to-camel-case: true
logging:
level:
root: info
org.springframework.web: info
# 打印sql
com.enjoylearning.mybatis.mapper: DEBUG
server:
port: 8081
3.启动类
为了不用在每个mapper.java中添加@Mapper注解,可以统一在启动类加上@MapperScan注解。
@SpringBootApplication
@MapperScan(basePackages = "com.enjoylearning.mybatis.dao")
@Slf4j
public class MybatisSpringbootDemoApplication {
public static void main(String[] args) {
log.info("------------------MybatisSpringbootDemoApplication-----------start ");
SpringApplication.run(MybatisSpringbootDemoApplication.class, args);
log.info("------------------MybatisSpringbootDemoApplication------------end ");
}
}
4.测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybatisSpringbootDemoApplication.class)
public class StudentMapperTest{
@Autowired
private UserInfoMapper userInfoMapper;
@Test
public void selectStudentById() throws Exception {
UserInfo userInfo = userInfoMapper.selectByPrimaryKey("1");
System.out.println("---->查询结果为={}" + userInfo);
}
}