第五篇:SpringBoot整合Mybatis
前言
前面两篇文章和读者聊了Spring Boot中最简单的数据持久化方案JdbcTemplate,JdbcTemplate虽然简单,但是用的并不多,因为它没有MyBatis方便,在Spring+SpringMVC中整合MyBatis步骤还是有点复杂的,要配置多个Bean,Spring Boot中对此做了进一步的简化,使MyBatis基本上可以做到开箱即用,本文就来看看在Spring Boot中MyBatis要如何使用。
工程创建
pom依赖
<!-- web支持: 1、web mvc; 2、restful; 3、jackjson支持; 4、aop ... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- servlet依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- tomcat 的支持. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- FreeeMarker模板引擎所需依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- springboot测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- jdbc依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- spring-boot mybatis依赖:注意:不要使用1.0.0版本,因为还不支持拦截器插件,我这里 1.1.1 目前可用 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>实体类
public class User {
private Long id;
private String username;
private String address;
// 省略get set
}application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource注解方式
mapper接口
@Mapper
public interface UserMapper1 {
@Select("select * from user")
List<User> getAllUsers();
@Results({
@Result(property = "id", column = "id"),
@Result(property = "username", column = "u"),
@Result(property = "address", column = "a")
})
@Select("select id as id, username as u, address as a from user where id = #{id}")
User getUserById(Long id);
@Select("select * from user where username like CONCAT(‘%‘,#{name},‘%‘)")
List<User> getUsersByName(String name);
@Insert({"insert into user(username, address) values(#{username},#{address})"})
@SelectKey(statement = "", keyProperty = "", before = false, resultType = Integer.class)
Integer addUser(User user);
@Update("update user set username = #{username}, address = #{address} where id = #{id}")
Integer updateUserById(User user);
@Delete("delete from user where id = #{id}")
Integer deleteUserById(Integer id);
}UserService
@Service
public class UserService1 {
@Autowired
private UserMapper1 userMapper1;
public List<User> getAllUser(){
return userMapper1.getAllUsers();
}
public List<User> getUsersByName(String name){
return userMapper1.getUsersByName(name);
}
public User getUserById(Long id){
return userMapper1.getUserById(id);
}
public Integer addUser(User user){
return userMapper1.addUser(user);
}
public Integer updateUserById(User user){
return userMapper1.updateUserById(user);
}
public Integer deleteUserById(Integer id){
return userMapper1.deleteUserById(id);
}
}xml方式
mapper接口
import java.util.List;
@Mapper
public interface UserMapper {
List<User> getAllUser();
Integer addUser(User user);
Integer updateUserById(User user);
Integer deleteUserById(Integer id);
}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.demo.dao.UserMapper">
<select id="getAllUser" resultType="com.demo.entity.User">
select * from user;
</select>
<insert id="addUser" parameterType="com.demo.entity.User">
insert into user (username,address) values (#{username},#{address});
</insert>
<update id="updateUserById" parameterType="com.demo.entity.User">
update user set username=#{username},address=#{address} where id=#{id}
</update>
<delete id="deleteUserById">
delete from user where id=#{id}
</delete>
</mapper>修改pom和application.yml


整体测试
package com.demo;
import com.demo.entity.User;
import com.demo.service.UserService1;
import com.demo.service.UserService2;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisTest {
@Autowired
private UserService1 userService1;
@Autowired
private UserService2 userService2;
//mybatis注解测试
@Test
public void addUser(){
User user = new User();
user.setUsername("2神经薛之谦2");
user.setAddress("上海");
int result = userService1.addUser(user);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void updateUser(){
User user = new User();
user.setId(3L);
user.setUsername("岳云鹏");
user.setAddress("北京");
int result = userService1.updateUserById(user);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void delUser(){
int result = userService1.deleteUserById(2);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void getUserById(){
User user = userService1.getUserById(1L);
System.out.println(user.toString());
}
@Test
public void getUserByName(){
List<User> users = userService1.getUsersByName("薛");
for (User user : users){
System.out.println(user.toString());
}
}
@Test
public void getAllUsers(){
List<User> users = userService1.getAllUser();
for (User user : users){
System.out.println(user.toString());
}
}
//xml测试
@Test
public void addUserXml(){
User user = new User();
user.setUsername("张佳宁");
user.setAddress("北京");
int result = userService2.addUser(user);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void updateUserXml(){
User user = new User();
user.setId(5L);
user.setUsername("薛之谦");
user.setAddress("北京");
int result = userService2.updateUserById(user);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void delUserXml(){
int result = userService2.deleteUserById(6);
System.out.println(result==1 ? "Success":"fail");
}
@Test
public void getAllUsersXml(){
List<User> users = userService2.getAllUser();
for (User user : users){
System.out.println(user.toString());
}
}
}原理分析
在SSM整合中,开发者需要自己提供两个Bean,一个SqlSessionFactoryBean,还有一个是MapperScannerConfigurer,在Spring Boot中,这两个东西虽然不用开发者自己提供了,但是并不意味着这两个Bean不需要了,在org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration类中,我们可以看到Spring Boot提供了这两个Bean,部分源码如下:
@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
return factory.getObject();
}
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType = this.properties.getExecutorType();
if (executorType != null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
} else {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@org.springframework.context.annotation.Configuration
@Import({ AutoConfiguredMapperScannerRegistrar.class })
@ConditionalOnMissingBean(MapperFactoryBean.class)
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() {
logger.debug("No {} found.", MapperFactoryBean.class.getName());
}
}
}从类上的注解可以看出,当当前类路径下存在SqlSessionFactory、 SqlSessionFactoryBean以及DataSource时,这里的配置才会生效,SqlSessionFactory和SqlTemplate都被提供了。