Maven项目&Spring+Mybatis AOP织入事务

2022-01-11  本文已影响0人  乘风破浪的姐姐

事务:就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

事务四个属性ACID
原子性(atomicity)
事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
一致性(consistency)
一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
隔离性(isolation)
可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
持久性(durability)
事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

使用 Maven 作为构建工具,整合Spring、Mybatis,代码实现
实体类

package com.sc.pojo;

import lombok.Data;

@Data
public class Member {
    private Long id;
    private String memberNo;
    private String mobile;
    private String openId;
    private Shop shop;
}
package com.sc.pojo;

import lombok.Data;

@Data
public class Shop {
    private int shopInfoId;
    private String shopName;
    private String appKey;
    private String appSecret;
    private Long shopId;
    private String shopCode;
    private String saasTenantCode;
}

业务接口:

package com.sc.service;

import com.sc.pojo.Member;
import java.util.List;

public interface MemberMapper {
    int deleteMember(Long id);
    int addMember(Member member);
}

接口实现类

package com.sc.service;

import com.sc.pojo.Member;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;

public class MemberMapperImpl implements MemberMapper {
    //sqlSession不用我们自己创建了,Spring来管理
    private SqlSessionTemplate sqlSession;


    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
 
    @Override
    public int deleteMember(Long id) {
        MemberMapper mapper = sqlSession.getMapper(MemberMapper.class);
        Member tdyMemberInfo = new Member();
        tdyMemberInfo.setMemberNo("20211209100001132");
        tdyMemberInfo.setMobile("18660461132");
        tdyMemberInfo.setOpenId("PDH2JKKE3JUKAG6M7V12332");
        mapper.addMember(tdyMemberInfo);
        return mapper.deleteMember(id);
    }

    @Override
    public int addMember(Member member) {
        MemberMapper mapper = sqlSession.getMapper(MemberMapper.class);
        return mapper.addMember(member);
    }

}

mapper.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="com.sc.service.MemberMapper">
    <resultMap id="memberResultMap" type="Member">
        <result property="id"  column="member_id"/>
        <result property="memberNo" column="member_no"/>
        <result property="mobile" column="mobile"/>
        <result property="openId" column="open_id"/>

        <!--关联对象property 关联对象在TdyShop实体类中的属性-->
        <association property="shop" javaType="Shop">
            <result property="shopInfoId" column="shop_info_id"/>
            <result property="shopId" column="shop_id"/>
            <result property="shopName" column="shop_name"/>
            <result property="appKey" column="app_key"/>
            <result property="appSecret" column="app_secret"/>
            <result property="shopCode" column="shop_code"/>
            <result property="saasTenantCode" column="saas_tenant_code"/>

        </association>
    </resultMap>
  
    <delete id="deleteMember" parameterType="long" >
        deleted from t_dy_member_info where member_id=#{id}
    </delete>

    <insert id="addMember" parameterType="Member">
        INSERT INTO t_dy_member_info
        (shop_id,member_code,member_no,mobile,mix_mobile,open_id,`level`,bind_status,bind_status_time,`point`,point_time,create_time,last_modify_time)
        VALUES (9730231,NULL,#{memberNo},#{mobile},NULL,#{openId},1,1,NULL,0,NULL,NULL,NULL)
    </insert>

</mapper>

上述mapper文件中, 故意把 delete 写成deleted。

数据库配置信息db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://XXXX:3306/dXXX_sit?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&serverTimezone=CST
jdbc.username=XXX
jdbc.password=XXX

Mybatis配置文件

<?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>
      <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
  
    <typeAliases >
        <package name="com.sc.pojo"/>
    </typeAliases>
  
</configuration>

spring配置文件

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

    <!-- 加载配置文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
 
    <!--配置数据源:数据源有非常多,可以使用第三方的,也可使使用Spring的-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </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 name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>


    <!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <!--利用构造器注入-->
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <bean id="memberMapper" class="com.sc.service.MemberMapperImpl">
        <property name="sqlSession" ref="sqlSession"/>
    </bean>

    <!--JDBC事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--配置哪些方法使用什么样的事务,配置事务的传播特性  这里的*代表所有方法-->
            <tx:method name="*" propagation="REQUIRED"/>
            <tx:method name="addMember" propagation="REQUIRED"/>
            <tx:method name="deleteMember" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>


    <!--配置aop织入事务-->
    <aop:config>
        <aop:pointcut id="txPointcut" expression="execution(* com.sc.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>
</beans>

测试类

 @Test
    public void test2()
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        MemberMapper mapper = (MemberMapper) context.getBean("memberMapper");

        int code2 = mapper.deleteMember(new Long(489));
        if(code2>0){
            System.out.println("删除成功");
        }else {
            System.out.println("删除失败");
        }
    }

如果mapper文件正确配置,结果就是 插入成功,删除失败。
因为mapper文件中,delete写成了deleted,所以执行结果,报错。发现插入失败,删除失败。
上述可以看出,Spring为我们提供了事务管理,只需要配置即可。
这里使用的是声明式事务管理:
1)将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
2)将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
使用Spring管理事务,注意头文件的约束导入 : tx

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

JDBC事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource" />
</bean>

配置好事务管理器后我们需要去配置事务的通知

<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
   <tx:attributes>
       <!--配置哪些方法使用什么样的事务,配置事务的传播特性  这里的*代表所有方法-->
       <tx:method name="*" propagation="REQUIRED"/>
<!--            <tx:method name="addMember" propagation="REQUIRED"/>-->
<!--            <tx:method name="deleteMember" propagation="REQUIRED"/>-->
   </tx:attributes>
</tx:advice>

spring配置文件中配置AOP
导入aop的头文件

<!--配置aop织入事务-->
<aop:config>
   <aop:pointcut id="txPointcut" expression="execution(* com.sc.service.*.*(..))"/>
   <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

以上即完成了AOP织入事务的全部过程。

上一篇 下一篇

猜你喜欢

热点阅读