I. What is Mybatis?
Mybatis is an excellent java-based persistence framework, which encapsulates jdbc internally, so that developers only need to pay attention to SQL statement s themselves, and do not need to spend energy to deal with the complicated process of loading driver, creating connection, creating state and so on. At the same time, mybatis provides dynamic SQL based on XML or annotation, which enables us to control and optimize SQL.
2. Springboot integrates Mybatis in two ways:
A. Spring Boot introduces automatic configuration, which makes it easier for developers to use. When we introduce mybatis-spring-boot-starter, spring boot configures mybatis components directly by default so that we can use mybatis directly. The method is as follows:
1. Introducing dependencies into pom.xml: (mainly Ali's druid database connection pool and mybatis-spring-boot-starter)
2. In application.yml (or. properties format), set the database and mybatis parameters:<?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>
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
In the Mybatis section, we declare the path of the. xml file corresponding to the Mapper class (the mapper folder under the resources root path), and the POJO location of mybatis.
So far, the configuration part of mybatis is over. We just need to write POJO,Mapper and Dao.
The Mapper class is the main tool we use to access databases. We can use annotations like @Select to write dynamic SQL directly on methods, or we can write a UserMapper.xml for Mapper to declare statements in an XML file. (idea has a Mybatis plug-in that highlights the way Mapper does not add statement, while alt+enter generates Mapper.xml. You can also add the following UserMapper.xml directly to the resources/mapper mentioned above.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); }
4. Write 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>
At this point, our Mapper is declared Bean and can be injected directly into Dao using @Autowire. The Dao part is easy to write and code directly.
5. writing 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. Write Spirngboot Junit test cases
Note that since my findUserByName() return value is User, there was an error calling this method when there were multiple users with the same name in the database. You can change the return value of this method to List < User > and leave the rest unchanged.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()); } }
At the same time, we can also customize Mybatis Config to configure Mybatis. There are two required classes for customizing Mybatis:
DataSourceConfig.class: Configure the database (druid is used here)
Mybatis Config. class: Configure Mybatis sqlSessionFactory, etc.
1. Dependencies required in pom. XML (mainly mybatis,mybatis-spring, spring-boot-starter-jdbc and Druid)
2. Configure database-related information in application.yml:<?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>
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 (configuring information in application.yml in our A method in the class)
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); } }
The following sections on UserMapper, XML file and DAO are omitted, just like in Method A.
Run our test case:
The result is that it doesn't work. Because when we customize Mybatis configuration, we also have to specify the path of Mapper to the Application. To solve this problem, we canpackage 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"); } }
1. Note @MapperScan directly on Application ("com.springboot.yanming.mybatisconfig.mapper")
2. Configure MyBatis Mapper Scanner Config, and configure the path to scan 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; } }
While I was studying, I found that a lot of information mentioned that because mapperScanner Configurer was executed earlier than MyBatis Config, sqlSession Factory could not be injected. But I did not report any errors through experiments, so I commented @AutoConfigureAfter (MyBatis Config. class).
The inappropriateness of P.S. article is also expected to be corrected.