The Mybatis door must go in. If you can't get in, isn't the SSM blocked?

Posted by upnxwood16 on Sat, 06 Nov 2021 00:26:23 +0100

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&amp;useUnicode=true&amp;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");
    

Topics: Java Database Back-end SSM