Day23 Spring transaction Xml configuration and annotation configuration***

Spring transaction management-preparation

  • (1) Spring's transaction implementation method:
    1. Programmatic transaction management
    2. Declarative transaction management (transaction management can be achieved by using aop xml or annotated configuration)
  • (2) Prepare the database
  • (3) POM.xml

sql

create database day23db ;
use day23db;
create table `account` (
  `id` int(8) not null  primary key auto_increment,
  `name` varchar(64) default null,
  `money` double default null
) ;

insert into account values(null,'jack',1000);
insert into account values(null,'rose',1000);

# 转账
update account set money=money-500 where `name`='jack';
update account set money=money+500 where `name`='rose';

pom.xml

   <dependencies>
        <!-- jdbc-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- ioc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!-- jdbctemplate-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <!-- test-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
       <!-- aop-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.2</version>
        </dependency>
    </dependencies>

Test class TestAccountService

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAccountService {
    
    
    @Autowired
    IAccountService service ;
    @Test
    public void test01(){
    
    
        //业务对象
        //IAccountService service = new AccountServiceImpl();
        //调用方法 translate(一个人转出,另一个转入,金额)
        service.translate("jack","rose",500.00);
    }
}

IAccountService

public interface IAccountService {
    
    
    //转账本身就是从一个账户减钱,另一个账户加钱
    void translate(String from, String to, double money);
}

AccountServiceImpl

@Service
public class AccountServiceImpl implements IAccountService{
    
    
    @Autowired
    IAccountDao dao ;

    @Override
    public void translate(String from, String to, double money) {
    
    
        //创建AccountDaoImpl
        //AccountDaoImpl dao = new AccountDaoImpl();
        //调用方法
        dao.translateOut(from,money);
        //除0异常
        System.out.println(1/0); 
        dao.translateIn(to,money);
        System.out.println("--translate");
    }
}

IAccountDao

public interface IAccountDao {
    
    
	//标记为过时
    @Deprecated
    void update(String account, double v);
    void translateOut(String account, double v);
    void translateIn(String account, double v);
}

AccountDaoImpl

@Repository
public class AccountDaoImpl implements IAccountDao {
    
    
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Override
    public void update(String account, double v) {
    
    
       System.out.println(account+" "+v);
       jdbcTemplate.update("update account set money=money+? where `name`=?",v,account);
    }

    @Override
    public void translateOut(String account, double v) {
    
    
        jdbcTemplate.update("update account set money=money-? where `name`=?",v,account);
    }

    @Override
    public void translateIn(String account, double v) {
    
    
        jdbcTemplate.update("update account set money=money+? where `name`=?",v,account);
    }
}

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

    <!-- 数据源-->
    <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/day23db"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean>
    <!-- jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>

    <!--包扫描创建对象 扫描包与它下面的子包中的所有类-->
    <context:component-scan base-package="cn.cyl"/>
    
</beans>

Spring transaction management-transfer-no transaction

Int i = 1/0 in the transfer method of AccountServiceImpl appeared 除0异常; before the problem was found, the transfer was successful. After the problem is found, the transfer fails and the transaction control is not received, resulting in 数据前后不一致.
Insert picture description here

Spring transaction management-transfer-xml transaction

The solution is to use spring xml-based transaction management.
Steps:
1. Configure 3 contents in bean.xml
1. Configure platform transaction manager (inject dataSource)
2. Write a tx: Advice to set transaction enhancement
3. Configure aop (Configuration of cut point, combination of cut point and enhancement);
Insert picture description here

Because you want to use tx tags, you must add tx constraints.
applicationContext.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:context="http://www.springframework.org/schema/context" 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
           http://www.springframework.org/schema/aop/spring-aop.xsd">


<!-- 数据源-->
    <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/day23db"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean>
    <!-- jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>

    <!--包扫描创建对象 扫描包与它下面的子包中的所有类-->
    <context:component-scan base-package="cn.cyl"/>

    <!--1.要在bean.xml中创建spring的平台事务管理器  (DataSourceTransactionManager   )  注入dataSource-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--2.我们需要创建一个 tx:advice 增强-->
    <!--里面定义了筛选那些方法进行事务控制, 设置事务的隔离级别规则,  设置事务传播行为的规则  , 设置事务超时时间  设置事务是否只读..-->
    <tx:advice id="adviceId" transaction-manager="transactionManager">
        <tx:attributes>
            <!--
                该增强中的规则:
                name代表筛选那些方法收到事务的增强
                isolation : 隔离级别 REPEATABLE_READ 可重复读
                propagation: 传播行为
                read-only: 是否为只读事务
                timeout: 事务是否超时
            -->
            <tx:method name="translate" isolation="REPEATABLE_READ"  propagation="REQUIRED" read-only="false" timeout="-1" />
        </tx:attributes>
    </tx:advice>

    <!--3.配置aop-->
    <aop:config>
        <!--3.1 配置切点-->
        <aop:pointcut id="translate" expression="execution(* cn.cyl.service.AccountServiceImpl.translate(..))"/>
        <!--3.2 配置切点和增强的组合-->
        <aop:advisor advice-ref="adviceId" pointcut-ref="translate"/>
    </aop:config>

</beans>

Spring transaction management-transfer-annotation

Use annotation transaction management:

  1. Re-copy the code of the dao layer and the code of the service layer (add @Repository @Service to the implementation class) when injecting, use @Autowried automatic injection
  2. Rewrite an applicationContext.xml (reserved: load db.properties, DataSource, JdbcTemplate, delete other xml configuration of the platform transaction manager); first 配置包扫描, add it to the xml again注解驱动 (支持注解方式的事务)
  3. Just give it to the AccountServiceImpl class 添加一个@Transactional注解.
    Adding to a method indicates that this method has a transaction, and adding to a class indicates that all methods under the class have a transaction.
  4. Test the transfer method of AccountService to see if it can control the transaction.

applicationContext.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:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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">

<!-- 数据源-->
    <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/day23db"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
    </bean>
    <!-- jdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="dataSource"/>
    </bean>

    <!--包扫描创建对象 扫描包与它下面的子包中的所有类-->
    <context:component-scan base-package="cn.cyl"/>

    <!--1.要在bean.xml中创建spring的平台事务管理器  (DataSourceTransactionManager   )  注入dataSource-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--2.配置注解驱动-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

AccountServiceImpl

@Service
//类上添加
//@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED ,timeout = -1)
public class AccountServiceImpl implements IAccountService{
    
    
    @Autowired
    IAccountDao dao ;
	
	//方法上添加
	@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED ,timeout = -1)
    @Override
    public void translate(String from, String to, double money) {
    
    
        //创建AccountDaoImpl
        //AccountDaoImpl dao = new AccountDaoImpl();
        //调用方法
        dao.translateOut(from,money);
        //除0异常
        System.out.println(1/0); 
        dao.translateIn(to,money);
        System.out.println("--translate");
    }
}

Spring transaction management-transfer-there are transactions

Int i = 1/0 in the transfer method in AccountServiceImpl appeared 除0异常; before the problem was found, the transfer was successful. After discovering the problem, because there is 事务控制, so proceed 回滚, let the transfer operation return to the original data, so let 数据前后一致.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43639081/article/details/109140184