Five articles teach you to master spring five

Integration of Spring and mybatis and weaving of transactions

Integrate Mybatis

Create dependency

We need junit, mysql driver, mybatis, spring webmvc, spring JDBC, aspectjweaver

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
</dependencies>

Review Mybatis

Set the static resource filtering of maven (otherwise, mapper.xml cannot be found will appear later)

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>
  1. Create a new user entity class (Note: it corresponds to the field of the user table in the database)

    package com.lwh.pojo;
    
    public class User {
        private int id;
        private String name;
        private String 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 + '\'' +
                    '}';
        }
    }
    
  2. Create a new UserMapper interface

    package com.lwh.mapper;
    
    import com.lwh.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        public List<User> selectUser();
    }
    
  3. Write usermapper xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.lwh.mapper.UserMapper">
    
        <select id="selectUser" resultType="User">
            select * from user;
        </select>
    </mapper>
    
  4. Write the configuration file mybatis config XML and bind usermapper XML (remember)

    <?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>
        
        <!--Set alias-->
        <typeAliases>
            <package name="com.lwh.pojo"/>
        </typeAliases>
        
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!--every last xml You have to register-->
        <mappers>
            <mapper resource="com/lwh/mapper/UserMapper.xml"/>
        </mappers>
    </configuration>
    
  5. Writing test classes

    @org.junit.Test
    public void t1() throws IOException {
        String resources="mybatis-config.xml";
        InputStream asStream = Resources.getResourceAsStream(resources);
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(asStream);
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
        /**Output:
        *	User{id=1, name='a', pwd='12345'}
    	*	User{id=2, name='b', pwd='123455'}
    	*/
        sqlSession.close();
    }
    

Gradually integrate Spring and mybatis

The purpose of spring is to hand over the creation and management of objects to the framework. We can just go in and get them when we need to use them. Therefore, the new keyword that appears many times in mybatis is not allowed. Therefore, all the operations of key objects of mybatis are left to spring, that is, bean configuration

Mode 1

Write the data source configuration in the Spring configuration file
<!--Configure data sources, using spring Data source replacement for mybatis The configuration used is Spring Provided by the framework JDBC,That's why we imported it before spring-jdbc Reasons for-->
<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?serverTimezone=Asia/Shanghai"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>
Give the sqlSessionFactory of MyBatis to Spring for hosting, that is, create a bean
<!--establish SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!--binding mybatis Configuration file for-->
    <!--This sentence stands for this sqlSessionFactory Already and spring With its own configuration file-->
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <!--This sentence stands for binding mapper,such mybatis No binding is required in the configuration file mapper Yes-->
    <property name="mapperLocations" value="classpath:com/lwh/mapper/*.xml"/>
</bean>
Give the sqlSessionTemplate of MyBatis to Spring for hosting and create a bean
<!--establish sqlSessionTemplate That is, we are mybatis Used in SqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <!--Only through the constructor assignment, you can see the source code SqlSessionTemplate There is a parameter constructor in and needs to be passed in SqlSessionFactory-->
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
The implementation class usermapperinpl needs to be added to the interface to inherit the interface UserMapper
package com.lwh.mapper;

import com.lwh.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper{

    private SqlSessionTemplate sqlSession;

    //Give spring an injected interface set method
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List<User> selectUser() {
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}

Then send this class to Spring for hosting

<!--Spring Managed implementation class-->
<bean id="userMapper" class="com.lwh.mapper.UserMapperImpl">
    <property name="sqlSession" ref="sqlSession"/>
</bean>
test
@org.junit.Test
    public void t1() throws IOException {
        ApplicationContext context = new ClassPathXmlApplicationContext("SpringApplication.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> users = userMapper.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
        /**
         * User{id=1, name='a', pwd='12345'}
         * User{id=2, name='b', pwd='123455'}
         */
    }

Mode 2 (simplified on the basis of mode 1)

The first two parts are the same. In the third step, we can write the implementation class directly without giving sqlsession to Spring for hosting, that is, without configuring the bean of sqlsession

UserMapperImpl2
package com.lwh.mapper;

import com.lwh.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {

    /**
     * SqlSessionDaoSupport This parent class has helped us to obtain sqlsession
     * However, the parent class SqlSessionDaoSupport still needs to obtain the object SqlSessionFactory, so the creation of SqlSessionFactory is essential
     * @return
     */
    @Override
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}
Leave the implementation class to Spring for hosting
<!--Spring Implementation class of hosting mode 2-->
<bean id="userMapper2" class="com.lwh.mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
test
@org.junit.Test
public void t2(){
    ApplicationContext context = new ClassPathXmlApplicationContext("SpringApplication.xml");
    UserMapper userMapper2 = context.getBean("userMapper2", UserMapper.class);
    for (User user : userMapper2.selectUser()) {
        System.out.println(user);
    }
    /**
     * Output:
     * User{id=1, name='a', pwd='12345'}
     * User{id=2, name='b', pwd='123455'}
     */
}

Declarative transaction

Transaction:

  • Either all succeed or all fail
  • Transaction is very important in project development, which involves the consistency of data
  • Ensure integrity and consistency

Transaction ACID principle

  • Atomicity
  • uniformity
  • Isolation
    • Multiple services may operate the same resource to prevent data corruption
  • persistence
    • Once the transaction is committed, it will be written to the physical file to persist the data

for example

Writing pojo classes

package com.lwh.pojo;

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 + '\'' +
                '}';
    }
}

Import maven dependencies

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.22</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.2</version>
    </dependency>
</dependencies>

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

Write the configuration file for the integration of Spring and mybatis, Spring Dao xml

<?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
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">

    <!--Configure data sources, using spring Data source replacement for mybatis The configuration used is Spring Provided by the framework JDBC,That's why before we import spring-jdbc Reasons for-->
    <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?serverTimezone=Asia/Shanghai"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--establish SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!--binding mybatis Configuration file for-->
        <!--This sentence stands for this sqlSessionFactory Already and spring With its own configuration file-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--This sentence stands for binding mapper,such mybatis No binding is required in the configuration file mapper Yes-->
        <property name="mapperLocations" value="classpath:com/lwh/mapper/*.xml"/>
    </bean>

    <!--establish sqlSessionTemplate That is, we are mybatis Used in SqlSession,This step can be omitted in the second implementation method!!!-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--Only through the constructor assignment, you can see the source code SqlSessionTemplate There is a parameter constructor in and needs to be passed in SqlSessionFactory-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

</beans>

Writing spring application bean configuration files

<?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
        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
    <import resource="Spring-dao.xml"/>
    <bean id="userMapperImpl" class="com.lwh.mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>
</beans>

Write UserMapper interface

package com.lwh.mapper;

import com.lwh.pojo.User;

import java.util.List;

public interface UserMapper {
    //increase
    public void add(User user);
    //delete
    public void delete(int id);
    //modify
    public void update(User user);
    //check
    public List<User> query();

}

Write usermapper xml

be careful! There is an error, "deletes"! In order to test, we need to know what happens when the transaction is not configured

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lwh.mapper.UserMapper">

    <select id="query" resultType="User">
        select * from user;
    </select>

    <insert id="add" parameterType="User">
        insert into user(id,name,pwd) values (#{id},#{name},#{pwd})
    </insert>

    <delete id="delete" parameterType="int">
        deletes from user where id=#{id}
    </delete>
</mapper>

Write the mybatis config 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>

    <typeAliases>
        <package name="com.lwh.pojo"/>
    </typeAliases>
</configuration>

Write UserMapperImpl

package com.lwh.mapper;

import com.lwh.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImpl implements UserMapper{

    private SqlSessionTemplate sqlSession;

    //Give spring an injected interface set method
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public void add(User user) {

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        mapper.add(user);

        mapper.delete(3);
    }

    @Override
    public void delete(int id) {

    }

    @Override
    public void update(User user) {

    }

    @Override
    public List<User> query() {
        return null;
    }
}

Writing test classes

There were two people with id 1 and 2 in the database. I want to insert a person with id 3 into it, and then delete it

import com.lwh.mapper.UserMapper;
import com.lwh.mapper.UserMapperImpl;
import com.lwh.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

    @org.junit.Test
    public void t1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("SpringApplication.xml");
        UserMapper userMapperImpl = context.getBean("userMapperImpl", UserMapper.class);
        userMapperImpl.add(new User(3,"Li Hua","12345"));
    }
}

Result analysis

Sure enough, an error was reported

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'deletes from user where id=3' at line 1

Because my delete statement is written incorrectly, this error is reported. We hope that after this method is executed, if there is an error, other operations on the database also need to be invalidated. It should be consistent and not semi correct. This is obviously unreasonable. We need to declare transactions in Spring

We made changes to the code

Modify spring Dao XML, add the following code

<!--combination AOP Implement transaction weaving-->
<!--Configure notifications for transactions-->
<tx:advice id="txAdvice" transaction-manager="transationManager">
    <tx:attributes>
        <!--propagation Indicates the propagation of a transaction-->
        <tx:method name="add" propagation="REQUIRED"/>
        <tx:method name="delete" propagation="REQUIRED"/>
        <tx:method name="update" propagation="REQUIRED"/>
        <tx:method name="query" propagation="REQUIRED"/>
        <!--Generally, you only need to configure the following statements. The example code indicates that a method can be configured-->
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* com.lwh.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>

You can test directly. After the deletion error is found, no record with id 3 will appear! Transaction weaving succeeded!
I wish you a happy study! Common progress~

Keywords: Java Maven Mybatis Spring

Added by c0le on Mon, 03 Jan 2022 20:40:11 +0200