Hello, today to share Mybatis summary, quickly take out a small book to write it down!
Mybatis
MyBatis, is the most popular durable layer frame in China
ORM is used to solve the problem of entity class and database table mapping. JDBC has been encapsulated, shielding the JDBCAPI low-level access details, avoid us and JDBCAPI cross, can complete the data persistence operation.
O – Object Java objects
R-relation is a table in a database
M – mapping mapping
Start fast
Mybatis official help document: mybatis.org/mybatis-3/z…
1. Create Maven project
2. Import Maven dependencies
Here, we import mybatis dependencies, mysql classes, and unit test dependencies
3. Configure the Maven plug-in
Here, we configure Maven’s compiled plug-in. We specify that both the source and compiled files are Java 1.8
<plugins> <! Plugins </groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugins> </build>Copy the code
4. Create a database and import the table
CREATE TABLE team
(
TeamId int NOT NULL AUTO_INCREMENT COMMENT ‘teamId ‘,
TeamName varchar(50) DEFAULT NULL COMMENT ‘teamName ‘,
Location varchar(50) DEFAULT NULL COMMENT ‘team location ‘,
CreateTime date DEFAULT NULL COMMENT ‘createTime ‘,
PRIMARY KEY (teamId
)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
5. Write the Mybatis configuration file
Examples of configuration files can be found directly on the official website
During future development, you are advised to create a document to store the rules for writing configuration files for convenient development
The contents of < property> can be obtained as configuration files, which we will cover later
6. Write entity classes
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Team {
private Integer teamId;
private String teamName;
private String location;
private Date createTime;
Copy the code
}
7, write mapper interface
public interface TeamMapper {
@return */ List< team > getAll();Copy the code
}
8. Write mapper implementation
The implementation is written in.xml files
Id: non-method on the interface
ResultTyoe: The return value of the interface method (the full class name must be written before configuration)
Note: xxxmapper. XML must have the same name as the corresponding mapper interface
<? The XML version = “1.0” encoding = “utf-8”? >
<select id="getAll" resultType="top.faroz.pojo.Team">
select * from team
</select>
Copy the code
You can also put the.xml implementation under Resources, but be sure to use the same name as the package:
9. Add mapper mapping to Mybatis configuration file
After writing the.xml implementation, be sure to add a Mapper map to the configuration file
<mappers>
<package name="top.faroz.dao"/>
</mappers>
Copy the code
10. Write Mybatis utility class
The utility class is used to create a singleton factory for sqlSession
And add a method to get the sqlSession connection
11, test,
@Test
public void getAllTest() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
List all = mapper.getAll();
for (Team team : all) {
System.out.println(team);
Copy the code
}
sqlSession.close();
}
The test results are as follows:
2. Log adding
1. Add Maven dependencies
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Copy the code
2. Add log4j configuration
log4j.properties
We can adjust the level of log output, including INFO, WARNING, and ERROR in addition to DEBUG
Global logging configuration info warning error
log4j.rootLogger=DEBUG,stdout
Console output…
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] – %m%n
Now it’s output on the console, and in the future, maybe our project will be deployed on the client’s server, we can fix the log information to some external file
3. Configure LOG in Mybatis
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
Copy the code
4. Perform tests
The console displays detailed log information
3. Object analysis of Mybatis
1, the Resources,
The Resources class, as the name implies, is used to read resource files. There are many ways to load and parse resource files and return different types of IO stream objects.
2, the SqlSessionFactoryBuilder is
The person who created the SqlSessionFactory will only be used once in the entire project to create the SqlSessionFactory. After using the throw
3, SqlSessionFactory
Create a singleton factory for sqlSession. There should be only one singleton of SqlSessionFactory in the entire project
4, SqlSession
A SqlSession corresponds to a database session, which begins with the creation of the SqlSession object and ends with the closing of the SqlSession object.
The SqlSession interface object is thread unsafe, so it needs to be closed by calling its close() method immediately before each database session ends. The session is needed again and created again.
4. Improved MybatisUtil
In the quick Start section, we have encapsulated the process of obtaining Mybatis sqlSession object into a utility class
However, sqlSession is not stored as a member variable in MybatisUtil, so we have to manually call our external sqlSession to execute the close. We can turn sqlSession into a member variable and then, in MybatisUtil, write a close method.
If sqlSession is used as a static member variable, it is not thread safe. If sqlSession is used as a static member variable, it is not thread safe. Putting it in MybatisUtil is bound to cause thread-related problems.
To solve this problem, we need to introduce ThreadLocal
1, ThreadLocal
2. Use ThreadLocal to overwrite
3, summary
I personally don’t recommend using sqlSession as a static member variable, and the official documentation doesn’t recommend it either. Again, the main purpose of this section is to introduce ThreadLocal
Input mapping
So in our previous tests, the input was a single value, so what if we had multiple values in our input?
1. Use subscripts (not recommended)
If you have more than one parameter, you can use:
# # {arg0}, {arg1}, # {arg2}… # or # {param0}, {param2}, # {param3}… To obtain different parameters
However, this method is not recommended
2. Use annotations
We can annotate the @param annotation in front of the parameters of the corresponding Mapper interface, and use the parameter names defined in the annotation directly in the.xml implementation class
Interface:
Team selectByNameAndLocation(@Param(“name”) String name,@Param(“location”) String location);
Implementation:
Testing:
@Test
public void selectByNameAndLocationTest() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
Team Team = mapper. SelectByNameAndLocation (” bucks “, “Milwaukee, Wisconsin,”);
System.out.println(team);
sqlSession.close();
}
3. Use Map
The parameters passed in can be those obtained from the map. XML file and must be consistent with the key value in the map
Interface:
Team selectByName(Map map);
Implementation:
select * from team;
Copy the code
3) Output map type
When we only need to query several columns of data in the table, we can use the SQL query result as the key and value of the Map. Generally, Map<Object,Object> is used.
Map is returned by the interface. The query result of the SQL statement can contain only one record at most. Greater than one record throws a TooManyResultsException. If there are multiple lines, use List<Map<Object,Object>>.
Map<Object,Object> queryTwoColumn(int teamId);
List<Map<Object,Object>> queryTwoColumnList();
2, resultMap
ResultMap allows you to customize the mapping between SQL results and Java object attributes. More flexibility in assigning column values to specified attributes.
Generally, id is used for primary key columns and result is used for other columns
Column: indicates the name of the column in the database table, which is case-insensitive. Property: indicates the name of the corresponding property in the entity class, which is case-insensitive. JavaType: indicates the type of the corresponding property in the entity class, which can be omitted. Mybatis will infer that jdbcType=” type of column in database”
<! -- Primary key column, use id--> < ID column="teamId" property="teamId" javaType="java.lang.Integer"></ ID ><! -- The remaining columns, Use result- >< result column="teamName" property="teamName" javaType=" java.lang.string "></result> <result column="location" property="location" javaType="java.lang.String"></result> <result column="createTime" property="createTime" javaType="java.util.Date"></result>Copy the code
When used, the return value is changed from the original resultType to our resultMap:
Using resultMap for attribute mapping can also solve the problem that attribute names are inconsistent with database table column names
3, database table column and entity class attribute inconsistent processing
1) Use resultMap to solve the problem
I said that, but I’m not going to show it here
2) Create an alias in SQL
If the name of the query is underlined, and the name of the poJO is humped, we can alias the result as follows:
select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id};
${$} ${$} ${$
This question is often examined by interview questions
#{} : represents a placeholder that tells Mybatis to use the actual parameter value instead. And execute SQL statements using the PrepareStatement object, #{… } instead of ‘? ‘in SQL statements . This is the preferred method in Mybatis, safe and fast.
In this way, YOU can prevent SQL injection.
: indicates that the string is replaced as is, notifying Mybatis to use {} : indicates that the string is replaced as is, notifying Mybatis to use: indicates that the string is replaced as is, notifying Mybatis to replace the location with the contained “string”. Connect SQL statements to the contents of ${} using Statement or PreparedStatement. Generally used for replacing table names, column names, sorting different columns and so on.
In this way, we can modify the columns of the SQL statement, for example, we have the following requirement:
To query user information based on name, age, address, etc., you need to write three SQL statements
select * from xxx where name = #{name}
select * from xxx where age = #{age}
select * from xxx where address = #{address}
As you can see, the only difference is after where. Here, we can replace where with ${}, so we don’t need to write as much SQL
select * from xxx where ${column} = #{columnValue}
${} is not a string concatenation method, so do not use the parameter, otherwise it may cause SQL injection problems. But why can it be used elsewhere in SQL? This is because if you write an SQL injected statement in a non-parameter place, it will cause an SQL statement error and therefore an error.
Mybatis global configuration file
1. Configuration overview
Configuration, a few configuration does not matter, but be sure to follow the following configuration
The configuration (configuration)
Properties: Load external configuration files, For example, load database connection information Settings-- global configuration parameters: for example log configuration typeAliases-- type alias typeHandlers---- type handler objectFactory----- objectFactory Plugins------ Plugins such as paging Plugins Environments---- Environment collection properties objects transactionManager dataSource Mappers-- mapper: Register mapping filesCopy the code
2. Properties
Mybatis can read external configuration files via property configuration, such as loading database connection information
1) Create a configuration file
In the Resources folder, create the jdbc.properties configuration file
jdbc.driver=com.mysql.cj.jdbc.Driver
The JDBC url = JDBC: mysql: / / 127.0.0.1:3306 / mybatis_study? useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
jdbc.username=admin
jdbc.password=123
2) Introduce configuration file information in Mybatis configuration
3) Read the configuration file
3. Settings
Important tuning Settings in MyBatis that change the runtime behavior of MyBatis. For example, our configured logging is one of the applications. For other information, refer to the configuration document
Mybatis.org/mybatis-3/z…
4, typeAliases
A type alias sets an abbreviated name for a Java type. It is only used for XML configuration and is intended to reduce redundant fully qualified class name writing.
1) Supported aliases
2) Customize the alias
A type alias sets an abbreviated name for a Java type. It is only used for XML configuration and is intended to reduce redundant fully qualified class name writing. Such as:
When configured this way, blogs can be used anywhere doma.blog.blog is used.
(Below 👇 this method should be more convenient)
You can also specify a package name, MyBatis will search for the desired Java Bean under the package name, for example:
<package name="top.faroz.pojo"/>
Copy the code
5. Mappers
Method 1: [Recommended use]
Method 2: Use class file binding
Note:
The interface has the same name as the configuration file
The interface and its Mapper configuration file must be in the same package
Method 3: Inject binding using scan packages
6.
There are three kinds of built-in data types (type = “[UNPOOLED | POOLED | JNDI]”) :
UNPOOLED – The implementation of this data source opens and closes connections on each request. It’s a bit slow, but for simple applications that don’t require high availability of database connections
POOLED – This data source implementation leverages the concept of “pooling” to organize JDBC connection objects, avoiding the initialization and authentication time required to create new connection instances. (Database connection pool)
JNDI – This data source implementation is intended for use in a container such as an EJB or application server, which can centrally or externally configure the data source and then place a data source reference to the JNDI context.
POOLED is used by default
7. TransactionManager
1) Manual transaction commit is required by default
Mybatis framework is the encapsulation of JDBC, so the transaction control mode of Mybatis framework, The commit mode itself is set using the COMMIT () and setAutoCommit() methods of the ROLLBACK ().connection objects of JDBC.
Automatic commit and manual commit, this tag is used to specify the transaction manager used by MyBatis. MyBatis supports two transaction manager types :JDBC and MANAGED.
JDBC: Using the TRANSACTION management mechanism of JDBC, the Connection object is committed by the commit() method and rolled back by the rollback() method. By default, MyBatis has turned off the automatic commit function and changed it to manual commit. As can be seen from the log, we all need to commit or roll back transactions by ourselves in the application.
MANAGED: The entire life cycle of a transaction is MANAGED by a container (such as the Spring container).
2) Automatically commit transactions
Relational mapping
1. One-to-one relationship
There’s a requirement that there’s a bunch of students, a bunch of students that correspond to a particular teacher, and now we’re going to query the properties of the students and the corresponding teachers
The SQL statement:
Student:
public class Student {
private int id;
private String name;
private Teacher teacher;
Copy the code
}
Teacher:
public class Teacher {
private int id;
private String name;
Copy the code
}
1), according to query nesting processing
Interface:
List getAll();
XML realize
This is equivalent to executing the query again in a resultMap
Testing:
2) According to the result nesting processing
This approach is similar to a union table query
In terms of convenience, the first method is obviously more convenient (less SQL writing).
But in terms of performance, the second one performs better (after all, you only need to query the database once)
2. One-to-many relationship
One-to-many is almost the same as many-to-one
For example, one teacher has more than one student
Environment setup, same as before
Writing entity classes
public class Student {
private int id;
private String name;
private int tid;
}
1), according to the query nested query
Interface:
List getAll();
XML realize
OfType refers to the generic type of the element in the collection
Testing:
@Test
public void getAllTest() { SqlSession sqlSession = MybatisUtil.getSqlSession(); TeacherMapper = sqlSession. GetMapper (teachermapper.class); / / TeacherMapper = sqlsession.getMapper (teachermapper.class); List<Teacher> all = mapper.getAll(); for (Teacher teacher : all) { System.out.println(teacher); } sqlSession.close(); }Copy the code
2), according to the results of the nested query
Interface:
List getAll();
XML implementation:
select * from teacher <where> <if test="name! =null">Copy the code
Concatenate multiple strings using the concat function
and name like concat(concat('%',#{name}),'%')
</if>
</where>
Copy the code
The use of the set tag in update
The forEach tag
Batch add
INSERT INTO team (teamName,location) VALUES <! --collection: a collection to walk through; Separator: Delimits the result of the walk with, Separator ="list" item="t" separator=","> (#{t.name},#{t.ocation}) </foreach>Copy the code
Batch delete
delete from team where teamId in <! --collection: a collection to walk through; Separator: Separates the result of the traversal. Separator: Separates the result of the traversalCopy the code
Open =”(” close=”)”: wrap the traversal result with open close –>
<foreach collection="list" item="teamId" separator="," open="(" close=")">
#{teamId}
</foreach>
Copy the code
SQL fragment
Extract SQL fragment:
title = #{title}
Copy the code
and author = #{author}
Copy the code
Reference SQL fragment:
Note:
It is better to define SQL fragments based on a single table to improve the reusability of fragments
Do not include WHERE in SQL fragments
11. Paging plug-ins
Paging plug-in, we use pageHelper
1. Start fast
Maven dependency
< the groupId > com. Making. Pagehelper < / groupId > < artifactId > pagehelper < / artifactId > < version > 5.1.10 < / version >Copy the code
2. Add plugin configuration to Mybatis global configuration file
<! -- pageHelper plugin --> <! Note that it is a PageInterceptor interceptor. Prior to version 5.0, it was a PageHelper. After 5.0 to replace PageInterceptor - > < plugin interceptor = "com. Making. Pagehelper. PageInterceptor" > <! --reasonable: paging rationalization parameter (default value is false). Query based on the parameter directly. When this parameter is set to true, the first page is queried when pageNum<=0, and the last page is queried when pageNum> Pages exceeds the total number. Dialects can be omitted and are automatically inferred from the parameter URL of the connection data --> <! --<property name="reasonable" value="true"/>--> </plugin> </plugins>Copy the code
3. Use plug-ins
2, PageHelper introduction
PageHelper intercepts query statements and adds paging statements
3. PageInfo Introduction
Can be used to print information about pages, such as total number of pages, current page, total page, etc
Xii. Cache
Through the use of cache, you can query the information in the first time, into the cache, so that in the second query, the cache will be removed, so as to reduce database pressure, improve query efficiency, solve the problem of high concurrency.
MyBatis also has level 1 cache and level 2 cache, and has reserved an interface to integrate third party cache.
1. Level 1 cache
Automatically enable sqlSession-level cache
The sqlSession object is constructed when the database is manipulated, and there is a (memory area) data structure (HashMap) in the object to store cached data. The cache data area (HashMap) between different SQLsessions does not affect each other.
The scope of level 1 cache is the same SqlSession. When the same SQL statement is executed twice in the same SqlSession, the data queried in the database will be written to the cache (memory) after the first execution, and the data will be obtained from the cache and will not be queried from the database for the second time, thus improving the query efficiency.
When a sqlSession ends, the level 1 cache in that sqlSession ceases to exist. Mybatis enables level 1 cache by default. The local cache stored in memory cannot be turned off. You can call clearCache() to clear the local cache, or change the scope of the cache.
1) Introduction to level 1 cache
When the user initiates the first query for team=1001, the user first searches the cache to see if there is an object for team=1001. If not, continue to send query statements to the data. After the query succeeds, the result of teamId=1001 will be stored in the cache.
When the user sends the second query team=1001, the user will first search the cache to see if there is any object team=1001, because the data has been stored in the cache after the first successful query, so the user can directly obtain the data from the cache, which means that there is no need to send the query statement to the database.
If the SqlSession executes commit(adding, deleting, or modifying an operation), the cache area corresponding to the SqlSession is cleared to avoid dirty reads.
** Prerequisite :**SqlSession is not closed.
2) The way to clear the cache
1s, session.clearcache ();
Execute update;
3, the session. The close ();
FlushCache =”true”;
5, the rollback;
6, commit.
2. Level 2 cache
Mapper level cache, which can cross sqlSession
1) Introduction to level 2 cache
Level 2 cache is shared by multiple SQLSessions and is scoped to the same namespace as mapper.
Different SQLSessions execute the SQL statement of the same namespace twice with the same parameters, that is, the same SQL statement is executed at last. After the first execution, the data queried in the database is written to the cache (memory). After the second execution, the data will be retrieved from the cache and will not be queried from the database, improving the query efficiency.
Level 2 caching is not enabled in Mybatis by default. You need to configure level 2 caching in setting. If there is data in the cache, it does not need to fetch it from the database, greatly improving system performance.
As with level 1 caching, once the add, delete, and commit is made, the cached data is cleared to avoid dirty data reads
Its schematic diagram is as follows:
2) Use level 2 cache
3) Disable the second-level cache
Why do I need to disable level 2 caching?
In some cases, some data is modified very frequently. Once the second level cache is enabled, the operation of clearing the cache is also very frequent, which increases the pressure on the database. We can disable the second level cache for these SQL queries:
Set useCache=false to set useCache=false to set useCache=false to set useCache=false to set useCache=false to set useCache=false to set useCache=false to set useCache=false to disable level 2 caching for the current Select statement. The default value of useCache is true. For some very important data do not put in the level 2 cache.
4) Cache property configuration
<property name="eviction" value="LRU"/><! LRU--> <property name="flushInterval" value="60000"/><! <property name="size" value="1024"/><! <property name="readOnly" value="true"/><! - read only - >Copy the code
The source code is as follows:
If you want to share the same cache configuration and instance in the namespace, you can use the cache-ref element to reference another cache.
Namespaces are really just XML implementations
// Reference the cache in my namespace.
Reverse generator
Using the reverse generator, you can automatically generate the code for the persistence layer from the database tables
1, configuration,
slightly
2, use,
Here are some of the points to note
1) Dynamic update/insert
The selective keyword indicates dynamic change
// Dynamic insert
mapper.insertSelective(User user);
// Dynamic update
mapper.updateByPrimaryKeySelective(User user);
For insert, do not write insert SQL where the property of the insert object is empty
In the case of update, the metadata area is not overwritten with the empty part of the new object
2), multi-condition query
Multi-condition query, need to use XxxExample
The steps are as follows:
// create an Example of the query object
EbookExample ebookExample = new EbookExample();
// create a container for query conditions
EbookExample.Criteria criteria = ebookExample.createCriteria();
//3, in the container, prevent multiple query conditions
criteria.andNameLike(“spring”); // fuzzy query
criteria.andNameEqualTo(“spr”); / / equal to
/ /… There are many more, with an equal number of query criteria to choose from for each attribute
// select * from ‘Example’
mapper.selectByExample(ebookExample);
Well, that’s all for today’s article, hoping to help those of you who are confused in front of the screen