MyBatis
If there is a problem, switch the version:
- jdk:1.8
- mysql:5.1.47
- maven 3.6.1
- IDEA
brief introduction
What is MyBatis
MyBatis is an excellent persistence layer framework, which supports custom SQL, stored procedures and advanced mapping. MyBatis eliminates almost all JDBC code and the work of setting parameters and obtaining result sets. MyBatis can configure and map primitive types, interfaces and Java POJO s (Plain Old Java Objects) to records in the database through simple XML or annotations.
How to get mybatis
maven warehouse: https://mvnrepository.com/artifact/org.mybatis/mybatis/3.5.7
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency>
GitHub address: https://github.com/mybatis/mybatis-3/releases
Chinese documents: https://mybatis.org/mybatis-3/zh/index.html
Persistence
Data persistence
- Persistence is the process of transforming program data in persistent state and transient state
- Persistence: database (jdbc), io file persistence
- Instantaneous: memory: power loss
Persistent layer
- Code block that completes the persistence work
- The layer boundary is very obvious
Why do you need MyBatis?
-
Help programmers store data into the database
-
Traditional jdbc code is too complex - > simplified - > framework
-
advantage:
- Easy to learn
- flexible
- Separation of sql and code to improve maintainability
- Provide mapping labels to support the mapping of orm fields between objects and databases
- Provide object relationship mapping labels to support object relationship construction and maintenance
- Provide xml tags to support writing dynamic sql
-
Many people use it!
The first MyBatis program
Idea: build environment - > Import mybatis - > write code - > test
1. Build database
#mybatis CREATE DATABASE mybatis; USE mybatis; CREATE TABLE USER( sid INT(20) NOT NULL PRIMARY KEY, sname VARCHAR(30) DEFAULT NULL, pwd VARCHAR(30) DEFAULT NULL )ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO USER(sid,sname,pwd) VALUES (1,"feliks","123456"), (2,"zhangsan","123456"), (3,"lisi","123456")
2. New project
Create a normal maven project
Delete src directory as parent project
Import maven dependencies
<!--Parent project--> <groupId>net.cqwu</groupId> <artifactId>Mybatis-Study</artifactId> <version>1.0-SNAPSHOT</version> <!--Import dependency--> <dependencies> <!--mysql drive--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
3. Create a module
- Write mybatis core configuration file
<?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 Core profile--> <configuration> <!--environment--> <environments default="development"> <environment id="development"> <!--Things Management--> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!--xml in & No, No & replace--> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <!--every last Mapper.xml All need to be in Mybatis Register in core profile--> <mappers> <mapper resource="net/cqwu/dao/UserMapper.xml"/> </mappers> </configuration>
- Write mybatis tool class
package net.cqwu.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; //Sqlsessionfactory -- > build sqlSession public class MybatisUtils { //Promote scope private static SqlSessionFactory sqlSessionFactory; static { try { //Step 1 of using Mybatis: get sqlSessionFactory object String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //Now that we have SqlSessionFactory, as the name suggests, we can get an instance of SqlSession from it. // SqlSession provides all the methods required to execute SQL commands in the database public static SqlSession getSqlSession(){ // SqlSession sqlSession = sqlSessionFactory.openSession(); // return sqlSession; return sqlSessionFactory.openSession(); } }
4. Write code
- Entity class
public class User { private int sid; private String sname; private String pwd; public User() { } public User(int sid, String sname, String pwd) { this.sid = sid; this.sname = sname; this.pwd = pwd; } //Omit getter setter toString
- Dao interface
public interface UserDao { List<User> getUserList(); }
-
Interface implementation class
From the original UserDaoImpl to a Mapper configuration file
<?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"> <!--Namespace namespace = Bind a corresponding Dao/Mapper Interface--> <mapper namespace="net.cqwu.dao.UserDao"> <!--Method name--> <!--Returns the fully qualified name--> <select id="getUserList" resultType="net.cqwu.pojo.User"> select * from mybatis.user </select> </mapper>
4. Test
- junit
public class UserDaoTest { @Test public void test(){ //Step 1: get SqlSession SqlSession sqlSession = MybatisUtils.getSqlSession(); //Step 2: execute SQL -- > method 1: getMapper UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> userList = mapper.getUserList(); //Method 2: old, not recommended // List<User> userList = sqlSession.selectList("net.cqwu.dao.UserDao.getUserList"); for (User user : userList) { System.out.println(user); } //Close SqlSession sqlSession.close(); } }
You may encounter problems:
- The profile is not registered
- Binding interface error
- Wrong method name
- Wrong return type
- Maven export resources
Summary:
Seven steps:
Three core interfaces of Mybatis
SqlSessionFactoryBuilder
This class can be instantiated, used, and discarded once created SqlSessionFactory, You don't need it anymore. therefore SqlSessionFactoryBuilder Instance The best scope is the method scope (that is, the local method variable). You can reuse SqlSessionFactoryBuilder To create multiple SqlSessionFactory Instance, but it's best not to keep it all the time, To ensure that all XML Parsing resources can be released to more important things.
SqlSessionFactory
SqlSessionFactory Once created, it should always exist during the operation of the application, There is no reason to discard it or recreate another instance. use SqlSessionFactory The best practice is not to create multiple times during application operation, Multiple reconstruction SqlSessionFactory It is regarded as a code "bad habit". therefore SqlSessionFactory The best scope for is the application scope. There are many ways to do this. The simplest is to use singleton mode or static singleton mode.
SqlSession
Each thread should have its own SqlSession example. SqlSession The instance of is not thread safe, so it cannot be shared, So its best scope is the request or method scope. Absolutely not SqlSession The instance reference is placed in the static field of a class, Not even instance variables of a class. And never SqlSession The reference of the instance is placed in any type In the managed scope of, such as Servlet In frame HttpSession. If you're using one now Web Framework, considering SqlSession Put it in one and HTTP The request is in a similar scope. In other words, every time you receive HTTP Request, You can open one SqlSession,When a response is returned, close it. This closing operation is very important. In order to ensure that the closing operation can be performed every time, You should put this close operation in finally Block in
Standard mode to ensure that SqlSession is turned off:
try (SqlSession session = sqlSessionFactory.openSession()) { // Your application logic code }
Errors encountered:
Test error
java.lang.ExceptionInInitializerError at net.cqwu.dao.UserDaoTest.test(UserDaoTest.java:15)
solve:
- Method 1: copy a copy of UserMapper.xml to the same path in target \ test classes
- Method 2: add the following configuration in pom.xml
- If an error is still reported, change true in true to false
maven may encounter the problem that the written configuration file cannot be exported or effective because the contract is greater than the configuration. Solution:
<!--stay build Medium configuration resourse,To prevent the failure of resource export--> <build> <resources> <resource> <directory>src/main/resource</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
Error in IDEA linked database
java.lang.RuntimeException: com.mysql.cj.exceptions.InvalidConnectionAttribute
Reason: serverTimezone is not specified
resolvent:
Fill in the following fields in the URL:
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC