[Spring Boot实战系列] - No.3 Spring boot 整合Mybatis
2017-11-27 21:50
1101 查看
一、Mybatis是什么:
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。同时,mybatis提供了基于XML或者基于注解的动态SQL的方式,使得我们可以控制和优化SQL。
二、Springboot整合Mybatis两种方式:
A. Spring Boot中引入了自动配置,让开发者利用起来更加的快捷,当我们引入mybatis-spring-boot-starter的时候,springboot会按照默认直接配置好mybatis的相关组件,使得我们可以直接使用mybatis。方法如下所示:
1. 在pom.xml中引入相关依赖:(主要是阿里的druid数据库连接池和mybatis-spring-boot-starter)
Mybatis部分,我们声明了Mapper类对应的.xml文件的路径(resources根路径下的mapper文件夹),和mybatis的POJO位置
到此为止,mybatis的配置部分已经结束了,我们只需要编写POJO,Mapper和Dao即可
3.编写User的Mapper类:
4. 编写UserMapper.xml
到此, 我们的Mapper就声明为Bean了,可以直接使用@Autowired注入到 Dao中。Dao部分的编写比较简单,直接上代码
5. 编写DAO
6. 编写Spirngboot Junit测试用例
B. 同时,我们也可以自定义MybatisConfig来配置Mybatis,自定义配置Mybatis有两个必需的类:
DataSourceConfig.class:配置数据库(这里使用druid)
MybatisConfig.class:配置Mybatis的sqlSessionFactory等
1. pom.xml中所需依赖(主要是mybatis,mybatis-spring,和spring-boot-starter-jdbc以及Druid)
3. DataSourceConfig.class
4. MybatisConfig.class(在类中配置了我们A方法中在application.yml中配置的信息)
后面关于UserMapper,XML文件和DAO部分省略,和A方法中一模一样
运行我们的测试用例:
1. 直接在Application上加注注解@MapperScan("com.springboot.yanming.mybatisconfig.mapper")
2. 配置MyBatisMapperScannerConfig,配置扫描Mapper所在的路径
在我进行学习的时候,我发现很多的资料都提到由于mapperScannerConfigurer的执行时间比较早,如果早于MyBatisConfig,那么sqlSessionFactory是无法注入的。但是我通过试验发现并没有报错,所以将@AutoConfigureAfter(MyBatisConfig.class)注释掉。
P.S.文章不妥之处还望指正
文本github源码地址
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。同时,mybatis提供了基于XML或者基于注解的动态SQL的方式,使得我们可以控制和优化SQL。
二、Springboot整合Mybatis两种方式:
A. Spring Boot中引入了自动配置,让开发者利用起来更加的快捷,当我们引入mybatis-spring-boot-starter的时候,springboot会按照默认直接配置好mybatis的相关组件,使得我们可以直接使用mybatis。方法如下所示:
1. 在pom.xml中引入相关依赖:(主要是阿里的druid数据库连接池和mybatis-spring-boot-starter)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot.yanming</groupId> <artifactId>mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>mybatis</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.29</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>2. 在application.yml(或者是.properties格式)中,设置数据库和mybatis参数:
spring: datasource: url: jdbc:mysql://localhost:3306/springboot username: root password: root type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 mybatis: mapper-locations: classpath:mapper/*Mapper.xml type-aliases-package: com.springboot.yanming.mybatis.model
Mybatis部分,我们声明了Mapper类对应的.xml文件的路径(resources根路径下的mapper文件夹),和mybatis的POJO位置
到此为止,mybatis的配置部分已经结束了,我们只需要编写POJO,Mapper和Dao即可
3.编写User的Mapper类:
package com.springboot.yanming.mybatis.mapper; import com.springboot.yanming.mybatis.model.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; /** * @Author: YanMing * @Description: * @Date: Created in 12:20 2017/11/27 */ @Mapper public interface UserMapper { //@Select("SELECT username,password,sex FROM user WHERE username = #{username}") User findUserByName(@Param("username")String username); void insertUser(User user); }Mapper类就是我们用来访问数据库的主要工具了。我们可以使用@Select等注解,直接在方法上边写动态SQL,也可以给Mapper编写一个UserMapper.xml,在XML文件中声明statement。(idea 有Mybatis 的插件,可以高亮Mapper中没有添加statement的方法,同时alt+enter生成Mapper.xml。也可以在上边提到的resources/mapper中直接添加以下UserMapper.xml)
4. 编写UserMapper.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.springboot.yanming.mybatis.mapper.UserMapper"> <sql id="ALL_COLUMN"> username,password,sex </sql> <insert id="insertUser" parameterType="com.springboot.yanming.mybatis.model.User"> INSERT INTO user(username, password, sex) VALUES ( #{username}, #{password}, #{sex} ) </insert> <select id="findUserByName" resultType="com.springboot.yanming.mybatis.model.User"> SELECT <include refid="ALL_COLUMN"></include> FROM user WHERE username = #{username}; </select> </mapper>
到此, 我们的Mapper就声明为Bean了,可以直接使用@Autowired注入到 Dao中。Dao部分的编写比较简单,直接上代码
5. 编写DAO
package com.springboot.yanming.mybatis.dao; import com.springboot.yanming.mybatis.model.User; import org.springframework.stereotype.Repository; /** * @Author: YanMing * @Description: * @Date: Created in 12:24 2017/11/27 */ public interface UserDao { User findUserByName(String username); void insertUser(User user); }
package com.springboot.yanming.mybatis.dao.impl; import com.springboot.yanming.mybatis.dao.UserDao; import com.springboot.yanming.mybatis.mapper.UserMapper; import com.springboot.yanming.mybatis.model.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; /** * @Author: YanMing * @Description: * @Date: Created in 19:15 2017/11/27 */ @Repository public class UserDaoImpl implements UserDao{ @Autowired UserMapper userMapper; @Override public User findUserByName(String username) { return userMapper.findUserByName(username); } @Override public void insertUser(User user) { userMapper.insertUser(user); } }
6. 编写Spirngboot Junit测试用例
package com.springboot.yanming.mybatis.mapper; import com.springboot.yanming.mybatis.MybatisApplication; import com.springboot.yanming.mybatis.dao.UserDao; import com.springboot.yanming.mybatis.model.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.*; /** * @Author: YanMing * @Description: * @Date: Created in 12:28 2017/11/27 */ @RunWith(SpringJUnit4ClassRunner.class) //@WebAppConfiguration @SpringBootTest(classes = MybatisApplication.class) @SpringBootConfiguration public class UserMapperTest { @Autowired UserDao userDao; @Test public void insertAUser(){ User user = new User(); user.setSex("man"); user.setUsername("yanming"); user.setPassword("123456"); userDao.insertUser(user); User res = userDao.findUserByName("xiaoming"); System.out.println(res.getPassword()); } }注意,由于我findUserByName()返回值是 User,当数据库中存在多个名字相同的用户的时候,调用此方法出错。可以将该方法返回值更改为List<User> ,其余不用更改。
B. 同时,我们也可以自定义MybatisConfig来配置Mybatis,自定义配置Mybatis有两个必需的类:
DataSourceConfig.class:配置数据库(这里使用druid)
MybatisConfig.class:配置Mybatis的sqlSessionFactory等
1. pom.xml中所需依赖(主要是mybatis,mybatis-spring,和spring-boot-starter-jdbc以及Druid)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.springboot.yanming</groupId> <artifactId>mybatisconfig</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>mybatisconfig</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.18</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> <version>1.5.8.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>2. 在application.yml中 配置数据库相关信息:
spring: datasource: url: jdbc:mysql://localhost:3306/springboot username: root password: root type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20
3. DataSourceConfig.class
package com.springboot.yanming.mybatisconfig.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; import java.sql.SQLException; /** * Created by arnold.zhu on 6/13/2017. */ @Configuration public class DataSourceConfig { @Value("${spring.datasource.url}") private String dbUrl; @Value("${spring.datasource.username}") private String username; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.driver-class-name}") private String driverClassName; @Value("${spring.datasource.initialSize}") private int initialSize; @Value("${spring.datasource.minIdle}") private int minIdle; @Value("${spring.datasource.maxActive}") private int maxActive; @Value("${spring.datasource.maxWait}") private int maxWait; @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.minEvictableIdleTimeMillis}") private int minEvictableIdleTimeMillis; @Value("${spring.datasource.validationQuery}") private String validationQuery; @Value("${spring.datasource.testWhileIdle}") private boolean testWhileIdle; @Value("${spring.datasource.testOnBorrow}") private boolean testOnBorrow; @Value("${spring.datasource.testOnReturn}") private boolean testOnReturn; @Value("${spring.datasource.filters}") private String filters; @Bean public ServletRegistrationBean druidServlet() { ServletRegistrationBean reg = new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings("/druid/*"); reg.addInitParameter("loginUsername", username); reg.addInitParameter("loginPassword", password); return reg; } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); filterRegistrationBean.addInitParameter("profileEnable", "true"); return filterRegistrationBean; } @Bean public DataSource druidDataSource() { DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName); datasource.setInitialSize(initialSize); datasource.setMinIdle(minIdle); datasource.setMaxActive(maxActive); datasource.setMaxWait(maxWait); datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); datasource.setValidationQuery(validationQuery); datasource.setTestWhileIdle(testWhileIdle); datasource.setTestOnBorrow(testOnBorrow); datasource.setTestOnReturn(testOnReturn); try { datasource.setFilters(filters); } catch (SQLException e) { e.printStackTrace(); } return datasource; } }
4. MybatisConfig.class(在类中配置了我们A方法中在application.yml中配置的信息)
package com.springboot.yanming.mybatisconfig.config; import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.TransactionManagementConfigurer; import javax.sql.DataSource; /** * @Author: YanMing * @Description: * @Date: Created in 14:29 2017/11/27 */ @Configuration @EnableTransactionManagement public class MyBatisConfig implements TransactionManagementConfigurer { @Autowired DataSource druidDataSource; @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean() { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(druidDataSource); bean.setTypeAliasesPackage("com.springboot.yanming.mybatisconfig.entity"); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); try { bean.setMapperLocations(resolver.getResources("classpath:mapping/*Mapper.xml")); return bean.getObject(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } @Bean public PlatformTransactionManager annotationDrivenTransactionManager() { return new DataSourceTransactionManager(druidDataSource); } }
后面关于UserMapper,XML文件和DAO部分省略,和A方法中一模一样
运行我们的测试用例:
package com.springboot.yanming.mybatisconfig.dao; import com.springboot.yanming.mybatisconfig.MybatisconfigApplication; import com.springboot.yanming.mybatisconfig.entity.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; import static org.junit.Assert.*; /** * @Author: YanMing * @Description: * @Date: Created in 19:06 2017/11/27 */ @RunWith(SpringJUnit4ClassRunner.class) //@WebAppConfiguration @SpringBootTest(classes = MybatisconfigApplication.class) @SpringBootConfiguration public class UserDaoTest { @Autowired UserDao userDao; @Test public void testUserDao(){ List<User> users = userDao.findUserByName("yanming"); System.out.println(users.size()+" user named yanming"); } }结果是并不能运行。因为在我们自定义配置Mybatis的时候还必须给Application指明Mapper所在的路径。解决这个问题可以
1. 直接在Application上加注注解@MapperScan("com.springboot.yanming.mybatisconfig.mapper")
2. 配置MyBatisMapperScannerConfig,配置扫描Mapper所在的路径
package com.springboot.yanming.mybatisconfig.config; import org.mybatis.spring.mapper.MapperScannerConfigurer; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration //@AutoConfigureAfter(MyBatisConfig.class) public class MapperScannerConfig { @Bean public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); mapperScannerConfigurer.setBasePackage("com.springboot.yanming.mybatisconfig.mapper"); return mapperScannerConfigurer; } }
在我进行学习的时候,我发现很多的资料都提到由于mapperScannerConfigurer的执行时间比较早,如果早于MyBatisConfig,那么sqlSessionFactory是无法注入的。但是我通过试验发现并没有报错,所以将@AutoConfigureAfter(MyBatisConfig.class)注释掉。
P.S.文章不妥之处还望指正
文本github源码地址
相关文章推荐
- Spring Boot 揭秘与实战(二) 数据存储篇 - MyBatis整合
- 2.SpringBoot系列-SpringBoot整合MyBatis
- SpringBoot系列2—整合Mybatis-plus
- Spring Boot系列之六 以注解方式整合MyBatis
- SpringBoot构建微服务实战 之 整合Mybatis(一)
- [Spring Boot实战系列] - No.2 Spring boot 整合Spring Security用户管理和用户权限管理
- CK1956-2017年最新项目实战Spring Boot视频微服务整合Mybatis
- CK1956-2017年最新项目实战Spring Boot视频微服务整合Mybatis
- Spring Boot系列之七 以xml整合MyBatis
- 【备忘】2017年最新 项目实战 Spring Boot视频教程 微服务整合Mybatis
- SpringBoot实战之11 整合mybatis
- 文章标题Spring Boot干货系列:(十一)数据存储篇-Spring Boot整合Mybatis通用Mapper插件
- 【SpringBoot系列1】SpringBoot整合MyBatis
- SpringBoot系列七:SpringBoot 整合 MyBatis(配置 druid 数据源、配置 MyBatis、事务控制、druid 监控)
- spring整合系列学习笔记——springBoot整合mybatis
- SSM系列1:简易详细的(Spring +Springmvc+Mybatis)框架整合搭建
- SpringBoot整合常用技术--MyBatis、Redis、定时任务、分页插件、逆向生成
- spring boot+mybatis+mysql+FreeMarker整合(1)
- SpringBoot(九)SpringBoot整合tk.mybatis
- springboot整合mybatis