SpringBoot integrates Mybatis, do you really understand the principle?

Preface

In the previous blog post, we have already had an in-depth understanding of the basic knowledge of SpringBoot, not only know what SpringBoot is, and how to quickly develop a SpringBoot application, for example ( Introduction to Spring Boot and Quick Setup ), but also in-depth study Its automatic configuration principle , I know that SpringBoot contains many Starters, but how do we use these Starters in the project? In this blog post, we focus on SpringBoot data access related content, not just simple integration, but to understand the principles, let's get started.

Learn about Spring Data

Insert picture description here

From the official website , it is not difficult to find that SpringData integrates a lot of data access layer technologies, such as: JDBC, JPA, MongoDB, Redis, Solr, Elasticsearch, Neoej, Hadoop. These are familiar to us, some of which are even We often use it in our work. So what does Spring Data do?

What is Spring Data

The mission of Spring Data is to provide a familiar and consistent Spring-based programming model for data access while still retaining the special characteristics of the underlying data storage. It makes it easy to use data access technologies, relational and non-relational databases, map-reduce frameworks and cloud-based data services.

speak English:

Spring Data is to simplify the construction of data access technologies based on Spring framework applications, including relational databases, NoSQL, Map-Reduce frameworks, cloud data services, etc., and aims to provide a universal and unified coding mode (but not a complete code Same), making it very easy to use any database in Spring.

To be more popular:

Spring Data aims to unify and simplify the operation of database access, regardless of whether it is a relational database or NoSQL data storage.

Insert picture description here

No matter what kind of persistent storage, Data Access Objects (DAO, or Data Access Objects) usually provide CRUD (create, read, update, delete) operations, query methods, sorting and paging methods for single domain objects. Spring Data provides a unified interface based on these levels (CrudRepository, PagingAndSortingRepository) and the implementation of persistent storage.

Using SpringData can greatly reduce the amount of data access layer (DAO) development. The only thing developers have to do is to declare the persistence layer interface, and Spring Data will do the rest for you!

From the above figure, we can find that SpringData is a higher level of abstraction, covering all aspects of database operations. Its features are as follows:


characteristic

  • Powerful repository and custom object mapping abstraction
  • Derive dynamic query from repository method name
  • Implement domain base class to provide basic attributes
  • Support transparent review (create, last change)
  • Can integrate custom repository code
  • Easily implement Spring integration through JavaConfig and custom XML namespace
  • Advanced integration with Spring MVC controller
  • Experimental support for cross-storage durability

how to choose

Insert picture description here

As you can see from the figure above, there are two frameworks for operating relational databases in Spring Data. One is Spring Data JDBC and the other is Spring Data JPA. How should we choose?


Spring Data JDBC

Spring Data JDBC, part of the Spring Data family, makes it easier to implement JDBC-based storage libraries. This module deals with enhanced support for the JDBC-based data access layer. It makes it easier to build Spring-driven applications that use data access technology.

The goal of Spring Data JDBC is to be conceptually simple. To achieve this, it does not provide caching, lazy loading, write-behind, or many other features of JPA. This makes Spring Data JDBC a simple, limited, and opinionated ORM.


Spring Data JPA

Spring Data JPA is part of the larger Spring Data family, which makes it easier to implement JPA-based repositories. This module deals with enhanced support for the JPA-based data access layer. It makes it easier to build Spring-driven applications that use data access technology.


How to choose between

We all know that the Java persistence layer framework can be roughly divided into two ways to access the database.

A kind of JDBC operation that encapsulates a certain degree of SQL core, such as: MyBatis.

The other is based on Java entity classes and establishes a mapping relationship between entity classes and database tables, which is what we call ORM frameworks, such as Hibernate, Spring Data JPA.

Spring Data JDBC is the underlying technical implementation of all ORM frameworks for operating relational databases. Spring Data JPA is an abstraction on top of JDBC. In order to make it easier to implement the data access layer based on the JPA specification, Hibernate is the specific implementation framework.

These two methods have their own advantages and disadvantages. You can choose the right framework according to your own business characteristics. Since the Mybatis framework is mostly used by Internet companies, I will mainly introduce how to use SpringBoot 2.4.4 to integrate Spring Data JDBC and Mybatis to access MySQL.


Know, what framework to choose, right?


Next, we create a user table and use Spring Data JDBC and Mybatis to access the MySQL database.

Table building statement:

CREATE DATABASE IF NOT EXISTS user_db_test;

DROP TABLE IF EXISTS t_user;

CREATE TABLE `t_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(64) NOT NULL COMMENT '用户姓名',
  `age` int(11) NOT NULL COMMENT '用户年龄',
  `mobile` varchar(11) DEFAULT NULL COMMENT '手机号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

Use Spring Data JDBC

1. Add dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

2. Add database driver

<!-- MYSQL 默认版本<mysql.version>8.0.23</mysql.version>-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Note: Since we are using SpringBoot 2.4.4, the underlying MySQL version is 8.0.23, you can replace it with the version corresponding to your own database.

3. Add configuration file

server:
  port: 8081

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/user_db_test
    username: root
    password: admin123
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: springboot-jdbc

4. Data access layer code

@Repository
public class UserRepository implements IUserRepository{

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Override
    public Integer getTotalCount() {
        Integer userCount = jdbcTemplate.queryForObject("select count(*) from t_user", Integer.class);
        return userCount;
    }

    @Override
    public User getUser(Integer userId) {
        return jdbcTemplate.queryForObject("select id,username,age,mobile from t_user where id = " + userId, new RowMapper<User>(){
            @Override
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
                User user = new User();

                user.setId(resultSet.getInt("id"));
                user.setUsername(resultSet.getString("username"));
                user.setAge(resultSet.getInt("age"));
                user.setMobile(resultSet.getString("mobile"));

                return user;
            }
        });
    }
    @Override
    public Integer insertUser(User u) {
        return jdbcTemplate.update("insert into t_user (username,age,mobile) values(?,?,?)", u.getUsername(), u.getAge(),u.getMobile());

    }

    @Override
    public Integer updateUser(Integer userId, String name) {
        return jdbcTemplate.update("update t_user set username=? where id=?", name, userId);
    }

    @Override
    public Integer deleteUser(Integer userId) {
        return jdbcTemplate.update("delete from t_user where id = ?", userId);
    }
}

5. Other codes, see details

Insert picture description here
<module>springboot-jdbc</module>

CodeChina: https://codechina.csdn.net/jiuqiyuliang/springboot-learning


principle

1. Analyze dependencies

The dependency of Spring Data JDBC is shown in the following figure:

Insert picture description here

The bottom layer of Spring Data JDBC depends on spring-boot-starter-jdbc. Spring-boot-starter-jdbc automatically configures spring-jdbc and HikariCP database connection pool.

2. Analyze automatic configuration

In the jdbc package under spring-boot-autoconfigure, you can see the automatic configuration class DataSourceAutoConfiguration.

Insert picture description here

DataSourceAutoConfiguration: Automatic configuration class of the data source

  • Modify the configuration DataSourceProperties related to the data source, starting with spring.datasource
  • The configuration of the database connection pool is automatically configured when there is no DataSource in your own container
  • The connection pool configured at the bottom is: HikariDataSource (HikariCP dependency is added at the bottom)
    @Configuration(proxyBeanMethods = false)
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
            DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
            DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
    protected static class PooledDataSourceConfiguration

DataSourceTransactionManagerAutoConfiguration: Automatic configuration of transaction manager

JdbcTemplateAutoConfiguration: Automatic configuration of JdbcTemplate, which can crud the database

  • You can modify this configuration item @ConfigurationProperties(prefix = “spring.jdbc” ) to modify the JdbcTemplate
  • @[email protected] JdbcTemplate; custom component

JndiDataSourceAutoConfiguration: Automatic configuration of jndi

XADataSourceAutoConfiguration: Distributed transaction related


Use mybatis

1. Add dependencies

<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.1.4</version>
</dependency>

2. Add database driver

<!-- MYSQL-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

3. Add configuration file

server:
  port: 8082

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/user_db_test
    username: root
    password: admin123
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: springboot-mybatis


# 配置mybatis规则
mybatis:
  config-location: classpath:mybatis/mybatis-config.xml  #全局配置文件位置
  mapper-locations: classpath:mybatis/mapper/*.xml  #sql映射文件位置

4. Data access layer code

@Mapper
public interface UserMapper {

    int getTotalCount();

    User getUser(Integer userId);

    int insertUser(User u);

    int updateUser(Integer userId, String name);

    int deleteUser(Integer userId);
}
<?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.liang.boot.mapper.UserMapper">

    <select id="getTotalCount" resultType="int">
      select count(*) from t_user
    </select>

    <sql id="Base_Column_List">
       id,username,age,mobile
    </sql>

    <resultMap id="BaseResultMap" type="com.liang.boot.domain.User">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="username" jdbcType="VARCHAR" property="username"/>
        <result column="age" jdbcType="INTEGER" property="age"/>
        <result column="mobile" jdbcType="VARCHAR" property="mobile"/>
    </resultMap>

    <select id="getUser" parameterType="int" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from  t_user where id = #{userId,jdbcType=INTEGER}
    </select>

    <insert id="insertUser" parameterType="com.liang.boot.domain.User">
        insert into t_user (username,age,mobile) values(#{username,jdbcType=VARCHAR},#{age,jdbcType=INTEGER},#{mobile,jdbcType=VARCHAR})
    </insert>

    <update id="updateUser">
        update t_user set username= #{name,jdbcType=VARCHAR} where id = #{userId,jdbcType=INTEGER}
    </update>
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from t_user where id = #{userId,jdbcType=INTEGER}
    </delete>

</mapper>

5. Other codes, see details

Insert picture description here

principle

1. Analyze dependencies

Insert picture description here

The bottom layer of mybatis-spring-boot-starter depends on spring-boot-starter-jdbc and mybatis-spring-boot-autoconfigure.

2. Analyze automatic configuration

You can see the automatic configuration class MybatisAutoConfiguration under mybatis-spring-boot-autoconfigure.

Insert picture description here

MybatisAutoConfiguration: the automatic configuration class of mybatis

  • Modify the configuration of mybatis MybatisProperties, start with mybatis
  • Introduce DataSourceAutoConfiguration automatic configuration, the principle is the same as above
@EnableConfigurationProperties(MybatisProperties.class) : MyBatis配置项绑定类。
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration{}

@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties

SqlSessionFactory: Automatically configured

SqlSessionTemplate: SqlSessionTemplate is automatically configured and combined with SqlSession

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

@Import(AutoConfiguredMapperScannerRegistrar.class);

Mapper: As long as the interface we write to operate MyBatis is standard @Mapper, it will be automatically scanned in

Best practice

  • Import mybatis-spring-boot-starter dependency
  • In the configuration application.yaml, specify the mapper-location location
  • Add the public configuration of mybatis in mybatis-config, such as cache
  • Write the Mapper interface and annotate @Mapper
  • Simple way to write SQL directly using annotations
  • Complicated method to write mapper.xml for binding mapping

to sum up

mybatis is a semi-automated ORM framework, which is a specific implementation framework of jdbc. It can help us realize features such as caching and delayed loading. This is why we use springboot to integrate mybatis more in our projects, while native jdbc .


Code example

Readers of the examples in this article can view the items in the warehouse below, as shown below:

<module>springboot-jdbc</module>
<module>springboot-mybatis</module>

If you are interested in these, welcome to star, follow, favorite, forward to support!


Author: Xiaoliang Program

It’s not easy for bloggers to write, so add some attention

Ask for attention, ask for likes, add attention to not get lost, thank you

Like is my biggest encouragement
↓↓↓↓↓↓