Mybatis is a persistence layer framework. In detail, it is a version persistence framework. It is configured through simple xml or annotations, so that the operation of the database is not so cumbersome;
What is mybatis
mybatis is a retrograde mapping framework, which is used to solve some problems encountered in database operation;
As the number of tables in the Hibernate framework increases, it is not as efficient as the number of tables in the Hibernate framework that can be used to perform dynamic queries. However, the number of tables in the Hibernate framework is also lower than that in the hibernis framework, and the number of tables that can be used to perform dynamic queries is also lower, Therefore, hibernate is suitable for projects that are not too complex and have low performance requirements;
Simple case -- database CURD
mybatis does not rely on spring, but they are usually used together. In actual development, we often encounter the query function. If it is developed through jdbc, the amount of code will be large. At the same time, if you want to modify the query, you need to modify the code of the whole program, which is very inconvenient;
Query user
In the actual development, the query operation usually involves the accurate query of single data and the fuzzy query of multiple data.
Step 1 ------ > > > create a maven project
Introduce corresponding dependencies -
lombok
mybatis
junit
mysql-connector
log4j
The following is the dependent code, which can be taken away directly
<dependencies> <!-- Automatic resource management getters,setters,equals,hashCode and toString--> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency> <!--test Junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies>
Then began to write code to achieve the desired function;
Take the background database of the store here as an example
You also need to prepare a data table - > > >
DROP TABLE IF EXISTS `bookstore`; CREATE TABLE `bookstore` ( `BookId` int NOT NULL, `BookName` varchar(255) DEFAULT NULL, `BookPublish` varchar(255) DEFAULT NULL, `BookPrice` double(10,2) DEFAULT NULL, `BookKind` varchar(16) DEFAULT NULL, `BookCount` int DEFAULT NULL, PRIMARY KEY (`BookId`), KEY `name_index` (`BookName`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; insert into `bookstore`(`BookId`,`BookName`,`BookPublish`,`BookPrice`,`BookKind`,`BookCount`) values (1001,'java introduction','Tsinghua Publishing House',56.80,'computer',70), (1002,'python thorough','Machinery Industry Press',78.60,'computer',130), (1003,'front end html','Tsinghua Publishing House',88.80,'computer',100), (1004,'feidu ','Zhangjiang Publishing House',25.70,'Literary classics',100), (1005,'Revealing Original Shape in Officialdom','Qingdao Publishing House',23.80,'Literary classics',100), (1006,'The Dream of Red Mansion','Qingdao Publishing House',36.80,'Literary classics',100), (1007,'Postpartum care of sows','Machinery Industry Press',27.80,'Practical technology',100), (1008,'Complete book of vehicle maintenance','Machinery Industry Press',26.80,'Practical technology',100), (1009,'How to please the rich woman','Happy Publishing House',125.00,'Life skills',100), (1010,'JVM tuning ','Beijing Science and Technology Press',68.90,'computer',120), (1011,'GO','Nanjing post and Telecommunications Publishing House',78.90,'computer',120), (1012,'Android introduction','Electronic Science and Technology Press',88.90,'computer',120), (1014,'Fruit tree planting','Northwest agriculture and Forestry Press',128.90,'Agriculture',120), (1015,'joke','Shanghai Publishing House',48.90,'life',120), (1111,'MQ Message queue','Peking University Press',98.90,'computer',120);
Step 2 --------- > > > write code to realize the function
Write an entity class
It seems that there are a lot of fields in the data table. Don't be afraid. lombok has been introduced to simplify the amount of code;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @AllArgsConstructor @NoArgsConstructor public class Book implements Serializable { private Integer BookId; private String BookName; private String BookPublish; private Double BookPrice; private String BookKind; private Integer BookCount; }
Is it very concise? set/get methods, toString,hashcode, etc. are implemented through lombok annotations instead of using them. If you encounter errors in the process of use, you may not have opened the lombok plug-in to make it take effect automatically
Opening method ----- > > >
Step 3 - > > > create a resource in the resources folder
Mybatis global configuration file mybatis config xml
Before that, you need to configure a jdbc configuration file. Of course, you can also write the database connection elements directly in mybatis config In XML
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="jdbc.properties"/> <settings> <!--appoint mybatis Log mode,If not specified,Automatic search processing--> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <!--The package scans the short path name of the alias class with lowercase initial--> <package name="com.gavin.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc_driver}"/> <property name="url" value="${jdbc_url}"/> <property name="username" value="${jdbc_username}"/> <property name="password" value="${jdbc_password}"/> </dataSource> </environment> </environments> <!--load mapper Mapping file--> <mappers> <mapper resource="com.gavin.mapper/BookMapper.xml"/> </mappers> </configuration>
jdbc.properties
jdbc_driver=com.mysql.cj.jdbc.Driver jdbc_url=jdbc:mysql://127.0.0.1:3306/gavin?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai jdbc_username=gavin jdbc_password=955945
If you want to print logs, you also need to use log4j or log4j2. This time, take log4j as an example
Create a log configuration file in the resources folder
log4j.properties
log4j.rootLogger=info,stdout,logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=d:/gavin.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %F %p %m%n
Finally, write the test class ----- >
Here, we need to understand the workflow of mybatis in order to better write test classes - > > >
First of all, mybatis requires two files ------ mybatis config XML (global configuration file) and mapper XML (mapping file). Of course, the file name does not have to be this
mybatis parses and creates sessions through these two files;
Each session will create a sqlsessionFactory object, and then create a sqlsession object through the factory object. The sqlsession object is used to receive requests, analyze which sql statements to execute, and then pass them to the executor for execution. statementHandler will be used to connect to the database during execution;
This is the basic working principle of mybatis;
Look at the picture - > >
Then start to write the test code, and complete the test writing through the test module;
public class Test1 { private SqlSession sqlSession =null; @Before public void init(){ InputStream resource =null; //Load Configure File try { resource= Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resource); sqlSession= build.openSession(true); } catch (IOException e) { e.printStackTrace(); } } @Test public void test(){ List<Book> list = sqlSession.selectList("findAll"); list.stream().forEach(System.out::println); } @After public void testClose(){ sqlSession.close(); } }
Operation results ----- > > >
Sometimes we will encounter some mistakes. Don't worry. Check the log carefully to see what went wrong;
In fact, the principle of adding, deleting, checking and changing questions is the same. We should pay attention to the path of mapper;
OK, le t's start to understand the writing format in each configuration file
Mapper file
Global profile
mybatisconfig.xml
Implement fuzzy query
Just modify the sql statement
However, this writing cannot prevent sql injection,
Check whether there is a suitable method for precompiling. However, no, it can only be spliced through strings,
Like this
Add data
The basic operations remain unchanged, that is, the methods of sql statements and database operations will change;
Note that this time is to insert data, so there is no need to write the return value, because there is no resultType attribute under the insert tag
If the content at the horizontal line of the picture is not removed, an error will be reported,
I don't know why I commented it out clearly, and then found that some things were missing... It's strange that mistakes always appear inadvertently;
Update data
Delete data
In this way, the addition, deletion, query and modification of the database by mybatis is over;
Let's make a little summary ------------ < > >
It can also be seen from the above operations that the operation of mybatis can be roughly divided into six steps;
1. Read the configuration file ----- mybatisconfig XML and mapper xml
2 load the configuration file and create sqlsessionFactory according to the configuration file
3. Create SqlSession according to sqlsessionFactory
4. SqlSession is responsible for contacting the database
5. Close SqlSession
Although on the surface, SqlSession is responsible for connecting to the database, in fact, the underlying layer is implemented by the extractor and statementhandler
Once you are familiar with the workflow, you need to learn more
The core object of MyBatis --------- > > >
SqlSessionFactory
SqlSessionFactory is a compiled memory image of a single database mapping relationship, which is built through the SqlSessionFactoryBuilder object, and the instance of SqlSessionFactory is built by the mybatis global configuration file
therefore
The code can be written down and the global configuration file can be read through the stream
getResourceAsStream method of Resources to read the configuration file, and then build a SqlSessionFactory object through the build of SqlSessionFactory builder;
SqlSessionFactory object is thread safe. Once created, it will exist throughout the execution of the application. If SqlSessionFactory of the same database is created multiple times, the resources of this database will be easily exhausted. Therefore, when building SqlSessionFactory instances, it is recommended to use the single column mode, that is, it is only instantiated once
SqlSession
The JDBC connection is encapsulated in sqlsession, which is a single thread object for the interaction between application and database;
SqlSession instances cannot be shared and are thread unsafe. Therefore, it is best to limit their scope of use to one request or one method. They must not be used in the static field, instance field or any type of management scope of a class. After using the SqlSession object, close it in time. You can usually close it in the finally block.
Common methods in SQL session
<T> T selectOne(String statement); //This method returns a generic object that executes the query result of the SQL statement. <T> T selectOne(String statement, Object parameter); //This method returns a generic object that executes the query result of the SQL statement. <E> List<E> selectList(String statement, Object parameter); //This method returns a collection of generic objects that execute SQL statement query results. <E> List<E> selectList(String statement, Object parameter); //This method returns a collection of generic objects that execute SQL statement query results. <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); //rowBounds is a parameter object for paging. This method returns a collection of generic objects that execute SQL statement query results. void select(String statement, Object parameter, ResultHandlerhandler); //The ResultHandler object is used to process the complex result set returned by the query, which is usually used for multi table queries. //insert,update,delete,commit and rollback are not displayed here
MyBatis profile
mybatis configuration attribute order
configuration
properties
settings
typeAliases
typeHandlers
objectFactory (object factory)
plugins
environments
Environment (environment variable)
Transaction manager
dataSource
databaseIdProvider (database vendor ID)
mappers
<settings> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="multipleResultSetsEnabled" value="true"/> <setting name="useColumnLabel" value="true"/> <setting name="useGeneratedKeys" value="false"/> <setting name="autoMappingBehavior" value="PARTIAL"/> <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/> <setting name="defaultExecutorType" value="SIMPLE"/> <setting name="defaultStatementTimeout" value="25"/> <setting name="defaultFetchSize" value="100"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="false"/> <setting name="localCacheScope" value="SESSION"/> <setting name="jdbcTypeForNull" value="OTHER"/> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings>
mapper profile
Error presentation ----- > > >
Let's talk about some small details in the global configuration file in mybatis
For example, an external configuration file JDBC is introduced in the above case development Properties is used for the introduction of variables. In fact, there is another operation, which is very similar to it, but there is no need to configure another file;
Then we can directly introduce a global variable --------- > > into the mybatis configuration file
General developers can or are used to putting the four elements outside the file (jdbc.properties) to reduce the coupling as much as possible;
However, there will be a problem. If both methods are configured, who will follow?
After the actual test, it is found that it follows the external configuration because
myabatis is when reading the configuration
First read the contents in the internal properties,
Then, after reading the information introduced by the external resource, if it has the same name,
The read external resource value will overwrite the internal read value;
Therefore, when temporarily modifying the database connection, it is OK as long as it does not have the same name;
If a property is configured in more than one place, MyBatis will be loaded in the following order:
First read the properties specified in the properties element body. Then, according to the resource in the properties element
Property reads the property file under the classpath, or reads the property file according to the path specified by the url property, and overwrites the previously read property with the same name.
Finally, read the attribute passed as a method parameter and overwrite the previously read attribute with the same name. Therefore, the attribute passed through the method parameter has the highest priority, resource/url
The configuration file specified in the properties takes second place, and the lowest priority is the property specified in the properties element.
At the same time, we can also specify the actual database environment in the code - > >
Set default values
Starting with MyBatis 3.4.2, you can specify a default value for placeholders.
Start the default value in the configuration file. In this case, we can set the default value for a configuration----
<property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/>
For example, we only set three values in the jdbc configuration file ------ > >
If you use the ":" character in the attribute name (such as db:username), or use the ternary operator of OGNL expression in SQL mapping (such as ${tablename! = null? Tablename: 'global_constants'}), you need to set specific attributes to modify the characters separating attribute name and default value. For example:
<properties resource="org/mybatis/example/config.properties"> <!-- ... --> <property name="org.apache.ibatis.parsing.PropertyParser.default-value-separator" value="?:"/> <!-- Modify the separator of the default value --> </properties>
<dataSource type="POOLED"> <!-- ... --> <property name="username" value="${db:username?:ut_user}"/> </dataSource>
#The difference between {} and ${}
When compiling ssql statements, we often use some parameters. When compiling, we are used to precompiling in traditional jdbc operations;
If precompiling is not used, sql injection is likely to occur, so the difference between # {} and ${} is actually the difference between precompiled and non precompiled. Here is a case-----
Set auto increment ----- >
It can be configured separately or in global configuration;