front
word
:
\textcolor{green} {Preface:}
preface:
❤️ What is Mybais? Have you studied database?
💢 Next, let's learn what Mybatis really is. Let's enter the door first~~~ 😤
💞 We must open the door and finish our first program 💞
💝 The code involved in the following article can be found on my gitee 💥 Learn MyBatis source code💥
📞 I don't know how to download it. You can read this article and learn this skill. It's very nice 🌏 How to use Git🌏
environment
- jdk1.8
- MySQL 5.7 or 8
- maven 3.6.1
- IDEA
Framework: configuration file; The best way is to look at the official website documents Introduction to official documents
1, Introduction
1. 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.
MyBatis was originally an open source project ibatis of apache. In 2010, the project was migrated from apache software foundation to google code and renamed MyBatis. Moved to Github in November 2013.
How to get Mybatis
-
maven warehouse
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency>
-
github
-
Very important Chinese documents Chinese documents
2. Persistence
An action
Data persistence
- Persistence is the process of transforming program data in persistent state and transient state
- Memory: loss upon power failure
- Database (JDBC), io file persistence
Why persistence?
- There are some objects we can't let him lose
- Memory is expensive
3. Persistent layer
A concept
Dao layer, Service layer, Controller layer
-
Code block that completes the persistence work
-
The layer boundary is very obvious
4. Why use Mybatis?
- Help us store data into the database
- convenient
- Traditional JDBC code is too complex – > simplified – > framework
- advantage:
- Easy to learn:
- flexible
- The separation of sql and code improves 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
5. Some notes on the official website
SqlSessionFactoryBuilder
This class can be instantiated, used, and discarded. Once SqlSessionFactory is created, it is no longer needed. Therefore, the best scope of the SqlSessionFactoryBuilder instance is the method scope (that is, local method variables). You can reuse SqlSessionFactory builder to create multiple SqlSessionFactory instances, 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
Once SqlSessionFactory is created, it should always exist during the operation of the application. There is no reason to discard it or recreate another instance. The best practice of using SqlSessionFactory is not to create it repeatedly during application operation. Rebuilding SqlSessionFactory multiple times is regarded as a code "bad habit". Therefore, the best scope of SqlSessionFactory 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 instance. The instance of SqlSession is not thread safe, so it cannot be shared, so its best scope is the request or method scope. Never put the reference of SqlSession instance in the static field of a class, or even the instance variable of a class. You must never put a reference to a SqlSession instance in any type of managed scope, such as HttpSession in the Servlet framework. If you are currently using a Web framework, consider putting SqlSession in a scope similar to HTTP requests. In other words, each time you receive an HTTP request, you can open a SqlSession and close it after returning a response. This close operation is very important. In order to ensure that the close operation can be performed every time, you should put this close operation in the finally block. The following example is a standard mode to ensure that SqlSession is closed:
try (SqlSession session = sqlSessionFactory.openSession()) { // Your application logic code }
Following this usage pattern in all code can ensure that all database resources can be shut down correctly.
2, The first Mybatis program
Idea: build environment – > Import Mybatis – > write code – > test
1. Build environment
1.1 building database
CREATE database `mybatis`; use `mybatis`; create table `user`( `id` int(20) not null primary key, `name` varchar(30) default null, `pwd` varchar(30) default null )engine=innodb default charset=utf8; insert into `user`(`id`, `name`, `pwd`) values(1,'hxl', '123456'),(2,'laoer', '123456'),(3,'laosan', '123456')
1.2 new project
1.2.1 create a common maven project
This has been blogged before, so I won't repeat it here. If you don't know, please click the portal ❤️ "An article teaches you how to solve maven" from environment to application - it's very worth reading ❤️
1.2.2 delete the src directory and make us the parent project
1.2.3 import maven dependency
Generally, we will set automatic import, but this is not available in the IDEA of the new version 2020.X, so we click the pattern at the top right after writing the file
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--Parent project--> <groupId>com.hxl</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>8.0.26</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project>
2. Create a new module
We create a module named mybatis-01, which is created using the normal maven. Note that the module is created in the Mybatis project
. The advantage is that we don't need to import packages such as mybatis every time.
2.1 write the core configuration file of mybatis
Let's connect to the database. I also sent this message to this place. If there is a time zone problem when connecting, we need to set the time zone to GMT (you can directly click set to modify it), and then connect.
Here we can find the url required for the following configuration.
Then we need to add a mybatis-config.xml in SRC - > main - > resources - > and add the following.
Note that the vlaue in it should be related to yourself instead of copying it,
<?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"> <!--Core profile--> <configuration> <environments default="development"> <environment id="development"> <!--transaction management--> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/> <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="com/hxl/dao/UserMapper.xml"/> </mappers> </configuration>
2.2 writing the tool class of mybatis
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 -- > is used to build sqlSession public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static{ try { //The first step in using mybatis is to get the 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. You can directly execute the mapped SQL statements through the SqlSession instance. public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
3. Write code
3.1 entity class
public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
3.2 Dao interface
List<User> getUserList();
3.3 interface implementation class
Replace the original UserDaoImpl with Mapper configuration file
mybatis.user here is because the database is connected in the idea. If it is not connected, write the table name directly
Create a UserMapper.xml under dao
<?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="com.hxl.dao.UserDao"> <!--select Query statement--> <!--there id Corresponding method name, resultType=result,The return type should be written in full--> <select id="getUserList" resultType="com.hxl.pojo.User"> select * from mybatis.user </select> </mapper>
4. Test
Successful results:
It is best to create a directory similar to dao under test for testing
public class UserDaoTest { @Test public void test(){ //Get SqlSession object SqlSession sqlSession = MybatisUtils.getSqlSession(); //When we get the object, we either get the sql from dao or mapper, but they are all the same //Next, we get his class through mapper, and then the interface can be used to return the interface type //Method 1: getMapper executes sql UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> userList = userDao.getUserList(); //Method 2: select directly through the inside, according to the returned value. Not recommended //List<User> userList = sqlSession.selectList("com.hxl.dao.UserDao.getUserList"); for (User user : userList) { System.out.println(user); } //Close SQLSession sqlSession.close(); } }
The officially recommended tests should be packaged in try catch
public class UserDaoTest { @Test public void test(){ //Get SqlSession object SqlSession sqlSession = MybatisUtils.getSqlSession(); try{ //When we get the object, we either get the sql from dao or mapper, but they are all the same //Next, we get the interface and return the interface type //Method 1: getMapper executes sql UserDao userDao = sqlSession.getMapper(UserDao.class); List<User> userList = userDao.getUserList(); //Method 2: select directly through the inside, according to the returned value. Not recommended //<User> userList = sqlSession.selectList("com.hxl.dao.UserDao.getUserList"); for (User user : userList) { System.out.println(user); } }finally { //Close SQLSession sqlSession.close(); } } }
Note:
Question1: Type interface com.hxl.dao.UserDao is not known to the MapperRegistry
The following registration is required in the mybatis config core configuration file
<!--every last Mapper.xml All need to be in Mybatis Register in core profile--> <mappers> <mapper resource="com/hxl/dao/UserMapper.xml"/> </mappers>
Question 2: #### The error may exist in com/hxl/dao/UserMapper.xml. This resource cannot be found
maven convention is larger than configuration. The configuration file we wrote cannot be exported or take effect
Add in pom.xml. Refresh maven after adding
<build> <resources> <resource> <directory>src/main/resources</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> </resource> </resources> </build>
Problem 3: binding interface error
Question 4: wrong method name
Question 5: incorrect return type
5. Change Dao to Mapper
We used to be UserDao, and then we changed it to UserMapper. At the same time, we also need to modify UserMapper.xml and the relevant code in Test.
3, CRUD
Write interface - > write sql statements in the corresponding mapper - > test
1. namespace
The package name in the namespace is consistent with the package name of Dao/Mapper interface!
2. select
- Select, query statement;
- id: is the method name in the corresponding namespace;
- resultType: return value of sql statement execution
- parameterType: parameter type
2.1 interface preparation
//Query all users List<User> getUserList(); //Query user by id User getUserById(int id);
2.2 write the sql statement in the corresponding mapper
<!--there id Corresponding method name, resultType=result,Write it all--> <select id="getUserList" resultType="com.hxl.pojo.User"> select * from mybatis.user </select> <select id="getUserById" parameterType="int" resultType="com.hxl.pojo.User"> select * from mybatis.user where id = #{id} </select>
2.3 testing
@Test public void test(){ //Get SqlSession object SqlSession sqlSession = MybatisUtils.getSqlSession(); try{ //When we get the object, we either get the sql from dao or mapper, but they are all the same //Next, we get the interface and return the interface type //Method 1: getMapper executes sql UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserList(); //Method 2: select directly through the inside, according to the returned value. Not recommended //<User> userList = sqlSession.selectList("com.hxl.dao.UserDao.getUserList"); for (User user : userList) { System.out.println(user); } }finally { //Close SQLSession sqlSession.close(); } } @Test public void getUserById(){ //Get SqlSession object SqlSession sqlSession = MybatisUtils.getSqlSession(); //When we get the object, we either get the sql from dao or mapper, but they are all the same //Next, we get the interface and return the interface type //getMapper execute sql UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.getUserById(1); //Method 2: select directly through the inside, according to the returned value. Not recommended //<User> userList = sqlSession.selectList("com.hxl.dao.UserDao.getUserList"); System.out.println(user); //Close SQLSession sqlSession.close(); }
3. insert
Add user
//insert a user int addUser(User user);
Write sql
<!--The properties in the object can be taken out directly--> <insert id="addUser" parameterType="com.hxl.pojo.User"> insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert>
Add, delete and modify transactions that need to be committed
//Add, delete and modify transactions that need to be committed @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); int r = userMapper.addUser(new User(4,"Old four","123456")); if(r>0){ System.out.println("Insert succeeded!"); } //Commit the transaction. Yes, very important sqlSession.commit(); sqlSession.close(); }
4. update
//Modify user int updateUser(User user);
<update id="updateUser" parameterType="com.hxl.pojo.User"> update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id} ; </update>
@Test public void updateUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); int r = userMapper.updateUser(new User(4,"Lao Lai","123")); if(r>0){ System.out.println("Modification succeeded!"); } //Commit the transaction. Yes, very important sqlSession.commit(); sqlSession.close(); }
5. delete
//delete user int deleteUser(int id);
<delete id="deleteUser" parameterType="int"> delete from mybatis.user where id = #{id} </delete>
@Test public void deleteUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.deleteUser(4); sqlSession.commit(); sqlSession.close(); }
6. Attention
- crud, we only need to modify two places, and we can add a test if necessary. UserMapper and UserMapper.xml.
- Adding, deleting, and modifying require a transaction to be committed. If the transaction is not committed, the database will not be successfully updated.
7. Error analysis
- Label matching cannot be wrong
- The value behind the resource binding mapper sold in mybatis-config.xml under resources should use / instead of. Because it represents the resource file path
- The program configuration file must conform to the specification
- NullPointerException, not registered with resource
- Chinese garbled code appears in the output xml file. Just delete the random code there
- There is no export problem with maven resources. As mentioned above, add a piece of code to the pom file.
8. Universal Map
Assuming that there are too many tables, fields or parameters in our entity class or database, we should consider using map. There are too many attributes. We only need to add what we need to add. If it is the above method, we need to write it all
//insert a user int addUser2(Map<String,Object> map);
<!--map It just needs to be with key Correspondence, transfer map of key--> <insert id="addUser2" parameterType="map"> insert into mybatis.user (id,name,pwd) values (#{userId},#{uerName},#{userPasswords}) </insert>
@Test public void addUser2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String,Object> map = new HashMap<String,Object>(); map.put("userId",5); map.put("userName","Old five"); map.put("userPassword","123456"); mapper.addUser2(map); sqlSession.commit(); sqlSession.close(); }
be careful:
Map passes parameters, and you can directly get the key from sql. [parameterType=“map”]
Object passes parameters, and you can directly get the attributes of the object in sql. [parameterType=“Object”]
If there is only one basic type parameter, you can get it directly in sql
Map or annotation is used for multiple parameters
9. Thinking questions
#Precompiling will be performed to ensure security and prevent sql injection
How to write fuzzy query?
//Fuzzy query user List<User> getUserLike(String value);
-
When Java code is executed, wildcard%%
<select id="getUserLike" resultType="com.hxl.pojo.User"> select * from mybatis.user where name like #{vlaue} </select>
@Test public void getUserLike(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<User> userList = userMapper.getUserLike("%h%"); for (User user : userList) { System.out.println(user); } sqlSession.close(); }
-
Using wildcards in sql splicing
<select id="getUserLike" resultType="com.hxl.pojo.User"> select * from mybatis.user where name like "%"#{vlaue}"%" </select>
List<User> userList = userMapper.getUserLike("h");