Spring学习笔记(七)——Spring整合Mybatis及事务管理

Spring整合mybatis示例:

首先创建一个User类:

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

创建这个类的映射接口UserMapper:

public interface UserMapper {
    public List<User> getUserList();
}

写这个接口的映射UserMapper.xml文件:

<?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">

<mapper namespace="mapper.UserMapper">
    <select id="getUserList" resultType="user">
        select * from user
    </select>
</mapper>

测试:
在这里插入图片描述
上面准备好后,就是Spring整合Mybatis后与单纯Mybatis不同的地方了:

mybatis配置文件与之前不同,之前在mybatis-config.xml中配置数据库连接的,现在要把这些放在spring的配置文件中,所以mybatis配置文件中只写类的别名和引用的Mapper。

<?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="pojo"/>
    </typeAliases>

<!--    <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/study?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>-->
<!--                <property name="username" value="root"/>-->
<!--                <property name="password" value="123456"/>-->
<!--            </dataSource>-->
<!--        </environment>-->
<!--    </environments>-->

    <mappers>
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>

</configuration>

在spring-config.xml中,我们要配置数据源DataSource、SqlSessionFactory对象以及SqlSessionTemplate对象(就是SqlSession)

SqlSessionTemplate 是 MyBatis-Spring 的核心,是继承 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession, SqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用

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

    <!--配置数据源DataSource-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/study?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--配置sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>
    
    <!--配置SqlSessionTemplate-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--只能使用构造器注入sqlSessionFactory,因为没有set方法-->
        <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
    </bean>

    <bean id="UserMapper" class="mapper.UserMapperImpl">
        <property name="sqlSession" ref="sqlSession"></property>
    </bean>
</beans>

创建UserMapper的实现类UserMapperImpl:

public class UserMapperImpl implements UserMapper{
    // 我们所有的操作都通过SqlSessionTemplate来执行,就像之前的sqlSession
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

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

测试:
在这里插入图片描述

Spring还可以通过SqlSessionDaoSupport来整合Mybatis:

再创建一个UserMapper的实现类UserMapperImpl2,这个类继承SqlSessionDaoSupport,SqlSessionDaoSupport 是一个抽象的支持类,用来为你提供 SqlSession,调用 getSqlSession() 方法你会得到一个 SqlSessionTemplate,之后可以用于执行 SQL 方法。

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> getUserList() {
        return getSqlSession().getMapper(UserMapper.class).getUserList();
    }
}

此时配置文件spring-config.xml可以省略不配置SqlSessionTemplate对象,但你需要为UserMapperImpl2配置参数sqlSessionFactory,因为SqlSessionDaoSupport需要sqlSessionFactory来创建sqlSessionTemplate

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

    <!--配置数据源DataSource-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/study?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--配置sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--绑定mybatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    </bean>

    <bean id="UserMapper2" class="mapper.UserMapperImpl2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>
</beans>

测试:
在这里插入图片描述

Spring中的事务管理:

Spring中的事务管理分两类:

  • 编程式事务:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码
  • 声明式事务:将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理,事务管理作为一种横切关注点,可以通过AOP方法模块化

事务的四大原则(ACID原则):

  • 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
  • 一致性(Consistency):事务前后数据的完整性必须保持一致
  • 隔离性(Isolation):事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离
  • 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

为上面的UserMapper接口增加两个方法:

public interface UserMapper {
    public List<User> getUserList();

    public int insertUser(User user);

    public int deleteUser(int id);
}

相应修改UserMapper.xml文件:

<?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">

<mapper namespace="mapper.UserMapper">
    <select id="getUserList" resultType="user">
        select * from user
    </select>
    <insert id="insertUser" parameterType="user">
        insert into user(id,name,password) values(#{id},#{name},#{password})
    </insert>
    <delete id="deleteUser">
        delete from user where id = #{id}
    </delete>
</mapper>

以及实现类UserMapperImpl:

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List<User> getUserList() {
        User user = new User(4, "小张", "123000");
        insertUser(user);
        deleteUser(3);
        return getSqlSession().getMapper(UserMapper.class).getUserList();
    }

    @Override
    public int insertUser(User user) {
        return getSqlSession().getMapper(UserMapper.class).insertUser(user);
    }

    @Override
    public int deleteUser(int id) {
        return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
    }
}

上面UserMapperImpl的getUserList方法包含先插入、再删除,最后得到得到用户列表三个动作,这三个动作就组成了一个事务。

当前User表:
在这里插入图片描述
未开启事务管理前,我们故意把UserMapper.xml中delete的SQL语句写错并测试,此时执行结果肯定报错:
在这里插入图片描述
但在报错的情况下,插入语句还是执行了,这明显不符合事务的ACID原则。

下面在Spring中通过AOP的方式开启声明式事务管理:

要在Spring容器中配置DataSourceTransactionManager对象:

	<!--配置DataSourceTransactionManager-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg index="0" ref="dataSource" />
    </bean>
    <!--结合AOP实现事务的织入-->
    <!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--给哪些方法配置事务-->
        <tx:attributes>
            <!--配置事务的传播特性propagation,默认是REQUIRED-->
            <tx:method name="insertUser" propagation="REQUIRED"/> <!--给指定方法名insertUser配置事务-->
            <tx:method name="*" propagation="REQUIRED"/> <!--给所有方法配置事务-->
        </tx:attributes>
    </tx:advice>
    <!--配置事务织入-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>

删除4号小张再测试:
在这里插入图片描述
此时插入也失败了,这才符合事务的ACID原则,要么都执行成功,要么都执行失败

把delete的SQL语句改正后再测试:
在这里插入图片描述
4号插入成功,3号也删除成功,此时都执行成功!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值