Persistence layer framework Mybatis

Overview

  • MyBatis is an open source project iBatis of apache. It was renamed MyBatis in 2010 and moved to Github in November 2013.
  • MyBatis is an excellent persistence layer framework. It encapsulates the process of operating the database of jdbc, so that developers only need to focus on the SQL itself without spending energy on processing such as registering drivers, creating connections, creating statements, and manually setting parameters. Result set retrieval and other jdbc complex process codes
  • Mybatis configures various statements to be executed through xml or annotations, and maps the java object and the sql in the statement to generate the final executed sql statement. Finally, the mybatis framework executes the sql and maps the result into a java object and returns
  • MyBatis supports custom SQL, stored procedures and advanced mapping

Execution process principle

  • Read the configuration file of MyBatis: mybatis-config.xml is the global configuration file of MyBatis, used to configure database connection information
  • Load the mapping file: The mapping file is the SQL mapping file. The SQL statements for operating the database are configured in this file and need to be loaded in the MyBatis configuration file mybatis-config.xml. The mybatis-config.xml file can load multiple mapping files, each file corresponds to a table in the database
  • Construct the session factory: Construct the session factory SqlSessionFactory through the environment configuration information of MyBatis
  • Create session object: The SqlSession object is created by the session factory , which contains all methods for executing SQL statements.
  • Executor executor: The bottom layer of MyBatis defines an Executor interface to operate the database. It will dynamically generate SQL statements that need to be executed based on the parameters passed by SqlSession, and is also responsible for the maintenance of the query cache.
  • MappedStatement object: There is a MappedStatement type parameter in the execution method of the Executor interface. This parameter is an encapsulation of mapping information and is used to store the id, parameters and other information of the SQL statement to be mapped.
  • Input parameter mapping: Input parameter types can be collection types such as Map and List, or basic data types and POJO types. The input parameter mapping process is similar to the JDBC process of setting parameters for the preparedStatement object.
  • Output result mapping: The output result type can be collection types such as Map and List, or basic data types and POJO types. The output result mapping process is similar to the JDBC result set parsing process.

SQL mapping file ( the core of concern during development )

Please refer to the official website: mybatis – MyBatis 3 | XML mapper

MyBatis paging plug-in PageHelper

Import Maven dependency packages

<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper</artifactId>
	<version>${pagehelper.version}</version>
</dependency>

<!--pageHelper使用了springboot的自动装配功能,
springboot启动时自动装配pageHelper相关的bean,所以在开发时无需手动添加任何注解,
spring.factories文件配置了自动配置类,Springboot启动时自动加载该对象到容器中 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
    <version>${pagehelper-spring-boot-autoconfigure.version}</version>
</dependency>

<!--pagehelper-spring-boot-starter启动包,
该包通过spring.provides配置文件把需要依赖的相关Jar包导入的工程中。
因此在springboot工程中只需要把pagehelper-spring-boot-starter引入即可,相关Jar包会自动导入
provides内容: pagehelper-spring-boot-autoconfigure,pagehelper,mybatis-spring-boot-autoconfigure,mybatis,mybatis-spring;
实际上这个启动包非必要的,可要直接引入相关的jar即可
 -->
<dependency>
	<groupId>com.github.pagehelper</groupId>
	<artifactId>pagehelper-spring-boot-starter</artifactId>
	<version>${pagehelper-spring-boot-starter.version}</version>
</dependency>

Enable paging ( PageHelper will automatically splice sql query data )

The core classes are PageHelper and PageInfo

PageHelper.startPage(pageNum,pageSize);//设置分页属性pageNum(第几页)和pageSize(每页显示的条数)
List<Users> list = userMapper.getUserList();//查询总数
PageInfo<Users> pageInfo = new PageInfo<>(list);//把查询到的结果封装到PageInfo类中

SpringBoot integrates MyBatis

You can refer to this blog post : Practical tutorial on integrating Mybatis with Spring Boot (dry information) - Zhihu (zhihu.com) [ The current process of integrating Mybatis for the company's microservice applications is basically the same as the introduction in this blog post ]

other

JDBC VS MyBatis

Characteristics of traditional JDBC access to databases

  • There is a lot of repetitive code in using JDBC to access the database (such as registering the driver, getting the connection, getting the transmitter, releasing resources, etc.)
  • JDBC itself does not have a connection pool and will frequently create and close connections, which is inefficient.
  • SQL is hard-coded in the program. Once the SQL is modified, the class needs to be recompiled.
  • The ResultSet object returned after executing the query SQL needs to be processed manually, which is sometimes particularly troublesome.

Features of mybatis framework for accessing databases

  • Mybatis encapsulates JDBC correctly, which can simplify JDBC code
  • Mybatis itself supports connection pools (other connection pools can also be configured), so it can improve the efficiency of the program.
  • Mybatis configures SQL in the mapper file. Modifying SQL only requires modifying the configuration file, and the class does not need to be recompiled.
  • Mybatis will help us process the ResultSet object returned after executing the query SQL and convert it into a Java object.
  • Almost all the problems in JDBC (complex code, too much repeated code, too many objects to operate, releasing resources, too troublesome processing of results, etc.) have been solved in the Mybatis framework.

Hibernate VS MyBatis 

  • ORM refers to object relational mapping, which is a persistence technology that persists objects in object-oriented programs into databases; Hibernate and Mybatis belong to the ORM framework
  • Hibernate is relatively complex and large, and the learning cycle is long; Mybatis mainly relies on sql writing, making developers feel more familiar
  • The specific relationships between Hibernate and the database are in XML, which is suitable for different databases; Mybatis relies on the database to write SQL, so its scalability and migration are relatively poor.
  • If you directly operate the database table without too much customization, it is recommended to use the Hibernate method; if you want to use SQL statements flexibly, it is recommended to use the MyBatis method.

Best practices for business batch operations

Add in batches

<insert id="batchSave" parameterType="java.util.List">
insert into User(title,content) values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.title},#{item.content})
</foreach>
</insert>
<!-- 参数类型是List<User>,实体集合 -->
  • MyBatis uses For loop to insert batches of data: Total time taken for 10,000 pieces of data: 26348ms
  • MyBatis uses a collection method (using <foreach> in xml) to add batches (recommended) : total time for 10,000 pieces of data: 521ms
  • SaveBatch method provided by MyBatis-Plus : Total time consumption for 10,000 pieces of data: 24674ms. The solution to this problem can be to add this attribute after the uri of the database configuration to enable the optimization of batch update statements rewriteBatchedStatements=true, which can reduce the time consumption to 500ms

Batch update

<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
update User
<set>
title = #{item.title}, content = #{item.content}
</set>
where id = #{item.id}
</foreach>
</update>
<!-- 参数类型是List<User>,实体集合 -->

batch deletion

<delete id="batchDel" parameterType="java.util.List">
delete from User where id in
<foreach collection="list" index="index" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
<!-- 参数类型是List<String>,id集合 -->

common problem 

The difference between #{} and ${} in Mybatis

  • #{} is a pre-compilation process, which can effectively prevent SQL injection (occurring during the compilation process) and improve system security. ${} is a simple string replacement.
  • When mybatis processes #{}, it will replace #{} in SQL with the number ?, and call the set method of PreparedStatement to assign. When mybatis processes ${}, it replaces ${} with the value of the variable.
  • Since ${} can cause sql injection, why do we need ${} when we have #{}? What is the meaning of its existence?
    • #{} is mainly used for pre-compilation, and the scenarios for pre-compilation are actually very limited, while ${} is used for replacement. Replacement will occur in many scenarios, such as SQL fragments to extract reusable SQL statements.

Mybatis often encounters the phenomenon of repeated data insertion in a high-concurrency environment ( the database table does not set unique fields ). How to solve this problem?

  • Use Redis lock, namely redis setnx key
    • Determine whether the database has the record data. If so, terminate. If there is no data, set the redis lock.
    • Use redis lock, because Redis is a single-threaded model, only one thread can execute successfully at the same time. Assume that thread a will succeed, and other concurrent threads b and c will fail.
    • Thread a that successfully sets key starts to insert data. Regardless of whether the data is inserted successfully or not, it will delete key at the end.
@RequestMapping("add")
public void add(HttpServletRequest request) throws Exception {
	List<Course> cList = testService.queryByName("key");//查询
	System.out.println(Thread.currentThread().getName() + "clist.size:" + cList.size());
	if (cList.size() == 0) {
		if (redisUtil.setnx("name_" + "key", "key") == 1) {//如果数据存在则返回0,不存在返回1
			Course course = new Course();
			course.setCname("key");
			try {
				testService.add(course);//插入
			} catch (Exception e) {
				redisUtil.del("name_" + "key");//插入出异常则删除
				throw e;
			}
			System.out.println(Thread.currentThread().getName() + "success");
			redisUtil.expire("name_" + "key", 3);//防止业务处理过程出现异常无法释放锁所以设置锁失效时间3秒
		} else {
			System.out.println(Thread.currentThread().getName() + "exists");
		}
	} else {
		System.out.println(Thread.currentThread().getName() + "false");
	}
}

How to establish a relationship between the Dao interface in Mybatis and the SQL in the XML file?

Guess you like

Origin blog.csdn.net/qq_34020761/article/details/132715739