Spring07 - integrate Mybatis

Review MyBatis

1. Import the dependencies required by MyBatis in Maven

<dependencies>
    <!--Mysql drive-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
    <!--MyBatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <!--junit-->
    <!--Junit unit testing -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

These are the dependencies required by MyBatis, and Spring has not been involved.

2. Create the configuration file mybatis config 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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="0723"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

You don't need DB here The properties file obtains the properties, and the later work will be left to Spring.

3. Create MyBatis tool class

public class MyBatisUtil {
    // 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();
        }
    }

    // Get SqlSession from SqlSessionFactory
    public static SqlSession getSqlSession(){
        // sqlSession is actually similar to connection
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }
}

The basic unified configuration is completed. The following is the entity class written for the corresponding database and the corresponding Mapper.

4. Write the entity class User, and the attribute corresponds to the field in the database

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
    private int id;
    private String name;
    private String pwd;
}

5. After writing the entity class, write the corresponding Dao layer interface, namely UserMapper, and put it under the Dao (or mapper) package

package com.qiyuan.dao;
...
public interface UserMapper {
    // Query all users
    List<User> getUserList();
}

6. If there is an interface, there must be its corresponding implementation, namely UserMapper XML, which is placed in the same package as the UserMapper interface (remember to let Maven export)

<?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 To bind a corresponding Dao/Mapper Interface, which is equivalent to implementing it-->
<mapper namespace="com.qiyuan.dao.UserMapper">
    <!--select Query statement, using alias configuration typeAlias -->
    <select id="getUserList" resultType="User">
        select * from user
    </select>
</mapper>

The alias is used here. It should be in mybatis config Configuration in XML

    <typeAliases>
        <package name="com.baifu.pojo"/>
    </typeAliases>

7. Then in mybatis config Register mapper in XML

    <mappers>
        <!--Required interface and its corresponding XML Same name and under the same package-->
       <mapper class="com.baifu.mapper.UserMapper"/>
    </mappers>

Registering bindings directly in class is relatively simple, but the interface and its corresponding XML name are required to be the same and under the same package.

8. Perform the test method

public class MyTest {
    @Test
    public void getUserListTest(){
        // Don't write notes. You can't understand it. Go to the ground!
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }
}

Error message sent by operation:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.baifu.mapper.UserMapper.getUserList

No usermapper was found under "target classes com Baifu mapper" xml, * * configure Maven so that the xml files in the java folder can be exported successfully** In POM Add in xml

<build>
    <resources>
        <!--Give Way java Under directory properties and xml Files can also be exported-->
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

The most basic MyBatis application is completed. Next, Spring is introduced.

MyBatis-Spring

There are two ways to use MyBatis through Spring: SqlSessionTemplate and SqlSessionDaoSupport.

1. Import dependency

To combine MyBatis and Spirng, in addition to importing the above MyBatis dependencies, of course, there are also Spring dependencies

<dependencies>
    <!--above MyBtais My bag-->
    ...
    <!-- Spring frame -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.9</version>
    </dependency>
    <!-- AOP -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version>
    </dependency>
    <!-- Spring Administration JDBC -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.3.9</version>
    </dependency>
    <!-- mybatis-spring -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.6</version>
    </dependency>
</dependencies>

Note that compared with previous Spring projects, there are more packages of Spring JDBC and MyBatis Spring. The former is used for Spring management database, and the latter is used to combine MyBatis and Spring.

What is mybatis spring?

MyBatis Spring will help you seamlessly integrate MyBatis code into Spring. It will allow MyBatis to participate in Spring's transaction management, create mapper s and sqlsessions and inject them into bean s, and convert MyBatis exceptions into Spring's DataAccessException. Finally, you can make the application code independent of MyBatis, Spring or MyBatis Spring.

2. Use SqlSessionTemplate

SqlSessionTemplate is the core of mybatis spring. As an implementation of SqlSession, this means that it can be used to seamlessly replace the SqlSession already in use in your code. SqlSessionTemplate is thread safe and can be shared by multiple Daos or mappers.

The steps to use MyBatis through Spring are

  1. Create Spring Dao XML configuration file (any name, which is actually the applicationContext.xml file of Spring) manages the configuration of the database, which is also equivalent to the MyBatisUtil tool class

    Configure data sourcedatasource

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--data source-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://111.230.212.103:3306/mybatis?userSSL=true&amp;
                    userUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="hsp"/>
        </bean>
      
    
    </beans>
    

    If the data source is configured in Spring, the data source in mybatis config can be deleted

    <!-- mybatis-config.xml -->
    <environments default="...">
    	<!--I can't use it. Delete it!-->
    </environments>
    
    
  2. Spring Dao. Created above Create the bean of sqlSessionFactory in the XML configuration file, set the dataSource property of the data source as the data source configured above, and set the configLocation property to bind the MyBatis configuration file

    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--binding MyBatis Configuration file!-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>
    

    This is equivalent to obtaining SqlSessionFactory instance in MyBatisUtil tool class!

    public class MyBatisUtil {
        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();
            }
        }
        ...
    }
    
    
  3. Its properties can also be configured in the bean of sqlSessionFactory, which is the same as that in mybatis config! If Mapper is registered

    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    	...
        <!--For example, register here Mapper -->
        <property name="mapperLocations" value="classpath:com/baifu/mapper/*.xml"/>
    </bean>
    
    
     I'll use it here before MyBatis Wildcards that cannot be used in because**Wildcards are created by Spring provide**of
    
     stay bean Configured in, mybatis-config Configured in mapper You can also delete it.
    
    <!-- mybatis-config.xml -->
    <mappers>
        <!--That's OK!-->
    </mappers>
    
    

    In this way, mybatis config There is almost no content in the XML (there is still an alias typeAlias). Although the alias can also be configured in the bean, it is best to put the alias typeAlias and settings in mybatis config XML for easy viewing and modification

    <!--Remaining mybatis-conifg content-->
    <?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>
        <typeAliases>
            <package name="com.baifu.pojo"/>
        </typeAliases>
    
    </configuration>
    
    
  4. With the configured sqlSessionFactory, you can use it to obtain sqlSession.

    Create a bean of sqlSession and inject sqlSessionFactory dependency

    <!-- SqlSessionTemplate namely SqlSession!-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--You can only inject with a constructor because it doesn't set method!-->
        <!-- Give it the factory and you can learn from it get reach SqlSession Yes-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
    
    

    SqlSessionTemplate class can only inject sqlSessionFactory dependency through constructor, which is a SqlSession.

  5. Here's the point! Due to the idea of object-oriented, the objects should be managed by Spring. Before using MyBatis, mapper XML acts as the implementation class of the interface. This implementation class cannot be managed by Spring, so we need to write a real interface implementation class to encapsulate mapper XML, to Spring management!

    Create the UserMapperImpl class and implement the UserMapper interface, that is, there are methods to operate the database

    public class UserMapperImpl implements UserMapper{
        // The original operation is implemented by SqlSession. Now SqlSessionTemplate is used
        // But it's still called sqlSession!
        private SqlSessionTemplate sqlSession;
    
        // Add a set method to inject properties
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        // Package here!
        public List<User> getUserList() {
            // IoC thought! You don't need to create a new sqlSession. You can use it after injection!
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            return userList;
        }
    }
    

    Among them, there is an attribute sqlSession (the same usage when it becomes SqlSessionTemplate) and its corresponding set method, which can be used after Spring dependency injection, which is equivalent to the previous one

    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    // Closing should be managed by Spring
    

    In this "real" implementation class (UserMapperImpl class), the "fake" implementation class (UserMapper.xml) method is invoked, which is equivalent to more than one layer of encapsulation, and also becomes a real class, which facilitates Spring management.

  6. The real class is managed by Spring, and dependency injection is carried out at the same time

        <bean id="userMapper" class="com.baifu.mapper.UserMapperImpl">
            <!--injection sqlSession!-->
            <property name="sqlSession" ref="sqlSession"/>
        </bean>
    

    At this time, after obtaining the userMapper object and executing the method, it will go to userMapper XML executes the corresponding statement, which is not different from the previous one, but has an additional layer of encapsulation to facilitate management!

  7. Method test

    public class MyTest {
        @Test
        public void MyBatisSpringTest(){
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
            UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
            List<User> userList = userMapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
        }
    }
    // results of enforcement
    /*
    User(id=1, name=www, pwd=99999)
    User(id=2, name=baifu, pwd=6666)
    User(id=3, name=Li Si, pwd=123890)
    */
    
    

Optimization: it can be noted that most configurations are in spring Dao XML file, this file does several things

  1. Configure the data source, that is, some configurations for connecting to the database (environment section in mybatis-config.xml)
  2. Create a bean of sqlSessionFactory for dependency injection (mapper in mybatis-config.xml, sqlSessionFactory in MyBatisUtil)
  3. Create a bean of sqlSession and inject sqlSessionFactory into it (sqlSessionFactory.openSession in MyBatisUtil)
  4. Create a bean with the real class UserMapperImpl and inject sqlSession into it

Among them, steps 1, 2 and 3 are all done by configuration and tools, which belong to the part with relatively few changes; Step 4 is a frequently performed step, such as adding bean s such as StudentMapperImpl and TeacherMapperImpl.

So take out the configuration in step 4 and leave steps 1, 2 and 3 to make spring Dao XML has become a relatively pure configuration file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- use Spring Data source replacement for MyBatis Data source for -->
    <!--data source-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="hsp"/>
    </bean>

    <!-- sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--binding MyBatis Configuration file!-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--For example, register here Mapper -->
        <property name="mapperLocations" value="classpath:com/baifu/mapper/UserMapper.xml"/>
    </bean>

    <!-- SqlSessionTemplate namely SqlSession!-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--You can only inject with a constructor because it doesn't set method!-->
        <!-- Give it the factory and you can learn from it get reach SqlSession Yes-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>
</beans>

As for the operation in step 4, create an object to be used, or put it in ApplicationContext Manage in XML!

Create ApplicationContext XML and introduce spring Dao. XML through the import tag XML, and hand over the real object to be used, namely userMapper, to it for management

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--adopt import Label introduction spring-dao.xml -->
    <import resource="spring-dao.xml"/>

    <bean id="userMapper" class="com.baifu.mapper.UserMapperImpl">
        <!--injection sqlSession!-->
        <property name="sqlSession" ref="sqlSession"/>
    </bean> 
    
</beans>

Remember to change the configuration file during testing due to spring Dao xml—>applicationContext. xml:

 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

The functions of these configuration files are clear. MyBatis config is responsible for some configuration (alias and setting) of MyBatis. Spring Dao manages the configuration of MyBatis connecting to the database, creating SqlSession and registering mapper. applicationContext integrates the configuration of spring (now spring Dao, spring MVC, etc.) and the objects to be used in management.

3. Use SqlSessionDaoSupport

Using SqlSessionDaoSupport is similar to using SqlSessionTemplate, but a little simpler.

As mentioned above, the UserMapperImpl class has a SqlSession attribute of SqlSessionTemplate type. The implemented method encapsulates the operation of using SqlSession on the database. Calling its method is equivalent to using SqlSession.

This method needs to inject sqlsession attribute before use, and sqlsession is created by SqlSessionFactory. That is, SqlSessionFactory and sqlsession bean s are required to use this method.

Using SqlSessionDaoSupport omits the step of creating the bean of SqlSession.

Create a UserMapperImpl2 implementation class, inherit the SqlSessionDaoSupport class, and implement the UserMapper interface

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> getUserList() {
        return null;
    }
}

Here's the point** There is a getSqlSession method in the SqlSessionDaoSupport class, which can directly obtain an sqlSession** Just use this sqlSession to perform database operations!

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    public List<User> getUserList() {
        SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserList();
        return userList;
    }
}

It can be used, but we must think about why it can be used** Why can the SqlSessionDaoSupport class return a SqlSession through the getSqlSession method** We know that SqlSession is created by SqlSessionFactory, so click to have a look

public abstract class SqlSessionDaoSupport extends DaoSupport {
	private SqlSessionTemplate sqlSessionTemplate;
    
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        // Get sqlSessionTemplate from factory
    }
}

i see! SqlSessionDaoSupport class needs to inject a sqlSessionFactory to obtain the sqlSessionTemplate object, which is the object returned!

Therefore, when registering the implementation class of UserMapperImpl2, sqlSessionFactory dependency should be injected

<bean id="userMapper2" class="com.baifu.mapper.UserMapperImpl2">
        <!--injection sqlSession!-->
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

It will obtain the sqlSessionTemplate through the injected sqlSessionFactory, that is, the SqlSession obtained in the previous way (see 2.2 / 4 for details).

Execute the test method, get the userMapper2 object, and the execution results are the same!

public class MyTest {
	@Test
    public void MyBatisSpringTest2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
        List<User> userList = userMapper.getUserList();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

This is done. Compared with the direct use of SqlSessionTemplate, SqlSessionDaoSupport encapsulates it. You can obtain sqlSession from SqlSessionDaoSupport without configuring the bean and injection of sqlSession (it is completed by the inherited SqlSessionDaoSupport class, and there is one step left).

summary

There are two ways to use mybatis spring

  • Using SqlSessionTemplate: it means using SqlSession directly. You need to inject SqlSession into the implementation class for use.

  • Use SqlSessionDaoSupport: the implementation class inherits the SqlSessionDaoSupport class, gives the factory to it (through injection), and can obtain SqlSession from it.

To use mybatis Spring, you need to create a connection with mapper XML corresponds to the implementation class, calling Mapper. in the implementation class. XML to realize database operation. Instantiate mapper The purpose of XML as an implementation class is to enable Spring to manage it.

reference resources: https://blog.csdn.net/qq_43560701/article/details/119960903

Keywords: Java Maven Mybatis Spring

Added by fgm on Tue, 25 Jan 2022 11:58:14 +0200