Spring boot2 series (21) mybatis integration

Time:2019-11-20

In the previous two articles, I talked with the readers about the simplest data persistence scheme in spring boot. Although it is simple, it doesn’t use much, because it’s not as convenient as mybatis. It’s a bit complicated to integrate mybatis in Spring + spring MVC. You need to configure multiple beans, which is further simplified in spring boot, so that mybatis can basically To do this out of the box, this article takes a look at how mybatis is used in spring boot.

Engineering creation

First, create a basic spring boot project, add Web dependency, mybatis dependency and MySQL driver dependency, as follows:

Spring boot2 series (21) mybatis integration

After creation, add Druid dependency and lock MySQL driver version. The complete dependency is as follows:

<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>2.0.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.28</version>
    <scope>runtime</scope>
</dependency>

In this way, the project is even created successfully. Note that the names of mybatis and Druid are different from those of other libraries. They belong to XXX spring boot stat mode, which means that the starter is provided by a third party.

Basic Usage

The usage of mybatis is basically the same as that of jdbctemplate. First, it is also the basic information of configuring database in application.properties:

spring.datasource.url=jdbc:mysql:///test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

After configuration, mybatis can create mapper to use. For example, I will create a usermapper2 directly, as follows:

public interface UserMapper2 {
    @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 username as u,address as a,id as id 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 = "select last_insert_id()", keyProperty = "id", 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);
}

This is to write SQL through full annotation instead of XML file.

@The four annotations of select, @ insert, @ update and @ delete correspond to the select, insert, update and delete tags in the XML respectively. The @ results annotation is similar to the resultmap mapping file in the XML (getuserbyid method aliases the fields of query results mainly to demonstrate to the partners@ResultsUse of annotations).

In addition, the @ selectkey annotation can be used to backfill the primary key. That is, when the data is inserted successfully, the inserted data ID will be assigned to the ID attribute of the user object.

After usermapper2 is created, mapper scanning must be configured. There are two ways. One is to add directly to usermapper2@MapperAnnotation. One disadvantage of this method is that all mappers need to be added manually. If one is left behind, an error will be reported. Another once and for all method is to directly add mapper scanning to the startup class, as follows:

@SpringBootApplication
@MapperScan(basePackages = "org.javaboy.mybatis.mapper")
public class MybatisApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisApplication.class, args);
    }
}

Well, after that, you can test mapper.

Mapper mapping

Of course, developers can also write SQL in XML, such as creating a usermapper, as follows:

public interface UserMapper {
    List<User> getAllUser();

    Integer addUser(User user);

    Integer updateUserById(User user);

    Integer deleteUserById(Integer id);
}

Then create the usermapper.xml file, as follows:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-21-mapper.dtd">
<mapper namespace="org.javaboy.mybatis.mapper.UserMapper">
    <select id="getAllUser" resultType="org.javaboy.mybatis.model.User">
        select * from t_user;
    </select>
    <insert id="addUser" parameterType="org.javaboy.mybatis.model.User">
        insert into user (username,address) values (#{username},#{address});
    </insert>
    <update id="updateUserById" parameterType="org.javaboy.mybatis.model.User">
        update user set username=#{username},address=#{address} where id=#{id}
    </update>
    <delete id="deleteUserById">
        delete from user where id=#{id}
    </delete>
</mapper>

Write the SQL corresponding to the method in the interface directly in the XML file.

So where is the usermapper.xml? There are two places to put it. The first is directly under the package where usermapper is located:

Spring boot2 series (21) mybatis integration

The usermapper.xml placed here will be automatically scanned, but there is another problem brought by maven, that is, the XML resources under the Java directory will be ignored when the project is packaged. Therefore, if usermapper.xml is placed under the package, the following configuration needs to be added to the pom.xml file to avoid the XML files under the Java directory being automatically ignored when packaging:

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>

Of course, usermapper.xml can also be directly placed in the resources directory, so you don’t need to worry about being ignored during packaging, but in the resources directory, you must create the same directory level as the mapper interface package directory, so as to ensure that the XML and mapper interface are together after packaging, otherwise the XML file will not be automatically scanned, and you need to add Add additional configuration. For example, I create a mapper directory under resources to put mapper files, as follows:

Spring boot2 series (21) mybatis integration

At this time, in application.properties, tell mybatis where to scan mapper:

mybatis.mapper-locations=classpath:mapper/*.xml

After this configuration, mapper can be used normally.Note that this way you do not need to configure file filtering in the pom.xml file.

Principle analysis

In SSM integration, developers need to provide two beans, one is sqlsessionfactorybean, and the other is mapperscannerconfigurer. In spring boot, although these two things are not provided by developers themselves, they do not mean that these two beans are not neededorg.mybatis.spring.boot.autoconfigure.MybatisAutoConfigurationClass, we can see that spring boot provides these two beans. Some of the source codes are as follows:

@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());
    }
  }
}

From the annotation on the class, it can be seen that when sqlsessionfactory, sqlsessionfactorybean and datasource exist in the current class path, the configuration here will take effect. Sqlsessionfactory and sqltemplate are provided. Why look at this code? In the next article, when brother song and everyone share the configuration of mybatis multi data source in spring boot, this will be an important reference.

Well, let’s start with this article. You can download the relevant cases from GitHub: https://github.com/lend/javaboy-code-samples

Pay attention to the public number [Jiangnan rain], focus on Spring Boot+ micro service and front end separation and other full stack technology, regular video tutorial sharing, focus on back to Java, receive Pine’s carefully prepared Java dry goods for you!
Spring boot2 series (21) mybatis integration