(8)Spring框架——TransactionManager事务管理(基于XML方法的声明事务)

news/2024/7/7 12:08:43

目录

 

一、XML声名事务概述

(一)PlatformTransactionManager

(二)TransactionDefinition

(三)TransactionStatus

二、举例

(一)、例子关键点描述

1、要在XML配置文件里面添加命名空间。

2、配置相应的模块。

(二)步骤

1、创建实体类

2、创建接口

3、创建接口实现类

4、创建测试类

5、创建XML配置文件

(三)实例


一、XML声名事务概述

事务管理的三个核心接口。

(一)PlatformTransactionManager

1、TransactionStatus getTransaction(TransactionDefinition definition):用于获取事物状态信息。

2、void commit(TransactionStatus status):用于提交事务。

3、rollback(TransactionStatus):用于回滚事务。

(二)TransactionDefinition

1、String getName()获取事务对象名称。

2、int getIsolationLevel():获取事务的隔离级别。

3、int getPropagationBehavior:获取事务的传播行为。

4、int getTimeout():获取事务的超时时间。

5、boolean isReadOnly():获取事务是否只读。


 

 

 

表一

 

属性名称描述
Propagation_RequiredRequired表示当前方法必须运行在一个事务环境当中,如果当前方法已处于事务环境中,则可以直接使用该方法;否则会开启一个新事务后执行该方法。(必须运行在事务中,如果已在直接使用该方法,如果不在则开启事务使用该方法)
PROPAGATION_SUPPORTSSUPPORTS如果当前方法处于事务环境中,则使用当前事务,否则不使用事务。(处于事务环境,则使用当前事务,否则不用。)
PROPAGATION_MANDATORYMANDATORY表示调用该方法的线程必须处于当前事务环境中,否则将抛异常。(必须处于当前事务中,否则将抛异常。)
PROPAGATION_REQUIRES_NEWREQUIRES_NEW要求方法在新的事务环境中执行,(如果已经在事务中,停止当前事务开启新事务,并在其中执行方法。如果不在事务中,开启一新事务并执行方法)
PROPAGATION_NOT_SUPPORTEDNOT_SUPPORTED不支持当前事务,总是在非事物状态执行。(处于事务环境会停止当前事务,执行方法。)
PROPAGATION_NEVERNEVER不支持当前事务,如果调用该方法的线程处于事务环境中将抛异常。
PROPAGATION_NESTEDNESTED即使当前执行的方法处于事务环境中,依然会启动一个新的事务,并且方法在嵌套的事务里执行;即使当前执行的方法不在事务环境中,也会启动一个新事务,然后执行该方法。(不管处不处于一个事务里,都开启一个新事务。并执行方法。)

(三)TransactionStatus

1、void flush();刷新事务。

2、boolean hasSavepoint():获取是否存在保存点。

3、boolean isCompleted():获取事务是否完成。

4、boolean isNewTransaction():获取是否是新事务。

5、boolean isRollbackOnly():获取是否回滚。

6、void setRollbackOnly():设置事务回滚。

二、举例

(一)、例子关键点描述

这个例子主要是讲XML配置事务管理。

1、要在XML配置文件里面添加命名空间。

这是额外添加的:xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

<?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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
</beans>

2、配置相应的模块。

(1)配置数据源,dataSource。

(2)配置JDBC模板,jdbcTemplate,通过bean的子元素property把dataSource通过ref把dataSource注入到jdbcTemplate这个对象里面,(注入后只要在这个类里面定义一个这类的类型变量就可以调用,dataSource这个类对象里面的方法。)

(3)配置accountDaoImpl,它是一个接口实现类,通过bean的子元素property把jdbcTemplate对象通过ref把实例注入到实现类里面。

(4)配置一个bean,这个bean是关于dataSourceTransactionManager的实例对象,通过bean的子元素property把dataSource通过ref注入到事务管理器中,我的理解这样可以控制到事务。

(5)编写通知:对事务进行增强通知,需要编写对切入点和具体执行事务的细节。(这个例子好像没有编写特别的通知和细节。)

(6)编写AOP:让spring自动对目标生成代理,需要使用AspectJ。形式:execution(* com.stx.chapter05.*.*(..))。把通知txAdvice这个bean对象注入到了这个id为txPointCut的bean

属性名称描述
name该属性为必选属性,它指定了与事务属性相关的方法名,其属性值支持使用通配符,如:‘*‘,’get*‘,'handle*',’*Order‘等。
propagation用于指定事务的传播行为,其属性值就是表一的值。他的默认值是REQUIRED
isolation该属性用于指定事务的隔离级别,其属性值可以为DEFAULT,READ_UNCOMMITTED,READ_COMMITTED,REPEATABLE_READ和SERIALIZABLE,其默认值为:DEFAULT。
read-only该属性用于指定事务是否只读,其默认值为false
timeout该属性用于指定事务超时的时间,其默认值为=1,即永不超时。
rollback-for该属性用于指定触发事务回滚的异常类,在指定多个异常类时,异常类之间以英文逗号分隔。
no-rollback-for该属性用于指定不触发事务回滚的异常类,在指定多个异常类时,异常类之间以英文逗号分隔。

(二)步骤

1、创建实体类

2、创建接口

3、创建接口实现类

4、创建测试类

5、创建XML配置文件

(三)实例

1、创建实体类,Account 

package com.stx.chapter05;

public class Account {
    private Integer id;
    private String userName;
    private Double balance;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", balance=" + balance +
                '}';
    }
}

2、创建接口,AccountDao 

package com.stx.chapter05;

import java.util.List;

public interface AccountDao {
//    添加
    public int addAccount(Account account);
//    更新
    public int updateAccount(Account account);
//    删除
    public int deleteAccount(int id);
//    通过id查询
    public Account findAccountById(int id);
//    查询所有账户
    public List<Account> findAllAccount();
//    转账
    public void transfer(String outUser,String inUser,Double money);
}

3、创建接口实现类,AccountDaoImpl 

package com.stx.chapter05;

import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.util.List;

public class AccountDaoImpl implements AccountDao{
//    声明JdbcTemplate属性以及setter方法
    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
//   添加账户
    @Override
    public int addAccount(Account account) {
//        定义SQL
        String sql = "insert into account(username,balance) values(?,?)";
//        定义数组来储存SQL语句中的参数
        /*
        * 定义一个数组,把对象获取出来。对象是方法参数传递进来的。
        * */
        Object[] obj = new Object[]{
                account.getUserName(),
                account.getBalance()
        };
        int num = this.jdbcTemplate.update(sql,obj);
        return num;
    }

//    更新账户
    @Override
    public int updateAccount(Account account) {
//        定义SQL
        String sql = "update account set username=?,balance=?where id=?";

        Object[] params = new Object[]{
          account.getUserName(),
          account.getBalance(),
          account.getId()
        };
        int num = this.jdbcTemplate.update(sql,params);
        return num;
    }
//删除账户
    @Override
    public int deleteAccount(int id) {
//        定义SQL
        String sql ="delete from account where id = ?";
        int num = this.jdbcTemplate.update(sql,id);
        return num;
    }
//查询一个数据
    @Override
    public  Account findAccountById(int id) {
//        定义sql语句
        String sql = "select * from account where id = ?";
//        创建一个新的对象BeanPropertyRowMapper
//        反射机制,获取这个类里面的实例,注入到这个类的。
        RowMapper<Account> rowMapper = new BeanPropertyRowMapper<Account>(Account.class);
//        将id 绑定到sql语句中,并通过RowMapper返回一个Object类型的单行记录。
        return this.jdbcTemplate.queryForObject(sql, rowMapper,id);
    }
//查询所有数据
    @Override
    public List<Account> findAllAccount() {
//        定义sql语句。
        String sql = "select * from account";
//        创建一个新的对象BeanPropertyRowMapper
        RowMapper<Account> rowMapper =
                new BeanPropertyRowMapper<Account>(Account.class);
//执行静态的sql查询,并通过RowMapper返回结果。
        return this.jdbcTemplate.query(sql,rowMapper);
    }
/*
* 转账
* inUser:收款人
* outUser:汇款人
* money :收款金额
* */
    @Override
    public void transfer(String outUser, String inUser, Double money) {
//        收款时,收款用户的余额 = 现有余额+所汇金额
        this.jdbcTemplate.update("update account set balance = balance + ? WHERE username = ?",money,inUser);
//        模拟系统运行时的突发性问题。
        int i = 1/0;
//        汇款时,汇款用户的余额=现有金额-所汇金额
                this.jdbcTemplate.update("update account set balance = balance - ? WHERE username = ?",money,outUser);
    }
}

4、创建测试类,JdbcTemplateTest 

package com.stx.chapter05;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class JdbcTemplateTest {
    /*public static void main(String[] args) {
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jt =(JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jt.execute("CREATE table message(id int PRIMARY KEY,name CHAR(20),sex CHAR(4),dress CHAR(80))");
        System.out.println("信息表message创建成功!");
    }*/
//    这是导入的单元测试。Junit4开源框架。
    @Test
    public void mainTest(){/*
        特别提醒,如果是放在src下面的其他包,需要将其整个包名暴露出来。
        例如 String XmlPath = "com\stx\chapter04\jdbc\applicationContext.xml";
        在传递给ClassPathXmlApplicationContext(XmlPath);
*/
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jt =(JdbcTemplate) applicationContext.getBean("jdbcTemplate");
        jt.execute("CREATE table account(id int PRIMARY KEY auto_increment,username varchar(20),balance double)");
        System.out.println("信息表message创建成功!");
    }
    @Test
    public void addAccountTest(){
        ApplicationContext applicationContext = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        AccountDao accountDao =(AccountDao) applicationContext.getBean("accountDao");
        Account account = new Account();
        account.setUserName("Rose");
        account.setBalance(8000.00);
        int num = accountDao.addAccount(account);
        if (num>0){
            System.out.println("成功插入!"+num+"条数据");
        }else {
            System.out.println("插入操作失败!");
        }
    }
    @Test
    public void updateAccountTest(){
        ApplicationContext app=
                new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountDao accountDao =(AccountDao) app.getBean("accountDao");
        Account account = new Account();
        account.setId(102);
        account.setUserName("Tom");
        account.setBalance(2001.00);
//        调用方法,把对象存入跟新语句。进入另外一个类的方法,
        int num = accountDao.updateAccount(account);
        if (num>0){
            System.out.println("成功修改!"+num+"条数据");
        }else {
            System.out.println("插入操作失败!");
        }
    }
    @Test
    public void deleteAccountTest(){
        ApplicationContext application=
                new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountDao accountDao =(AccountDao) application.getBean("accountDao");
        int num = accountDao.deleteAccount(102);
        if (num>0){
            System.out.println("删除成功!"+num+"条数据");
        }else {
            System.out.println("删除操作失败!");
        }
    }
//
    @Test
    public void findAccountByIdTest(){
//        加载配置文件
        ApplicationContext application=
                new ClassPathXmlApplicationContext("applicationContext.xml");
//        获取AccountDao实例
        AccountDao accountDao =(AccountDao) application.getBean("accountDao");
    Account account=accountDao.findAccountById(103);
        System.out.println(account);
    }
    @Test
    public void findAccountAllTest(){
//        加载配置文件
        ApplicationContext application=
                new ClassPathXmlApplicationContext("applicationContext.xml");
//        获取AccountDao实例
        AccountDao accountDao =(AccountDao) application.getBean("accountDao");
        List<Account> accounts = accountDao.findAllAccount();
        for (Account act:accounts){
            System.out.println(act);
        }
    }

//      测试类,转账方法。
@Test
public void transaction(){
//        加载配置文件
    ApplicationContext application=
            new ClassPathXmlApplicationContext("applicationContext.xml");
//        获取AccountDao实例
    AccountDao accountDao =(AccountDao) application.getBean("accountDao");
//    调用实例中的转账方法。
    accountDao.transfer("Jack","Rose",100.0);
//    输出提示信息。
    System.out.println("转账成功!");
}
}

5、创建XML配置文件,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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!--    1、配置数据源,连接数据库。-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--        数据库驱动-->
<!--        property都是通过setter赋值,后面的是要设置的参数-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<!--        连接数据库的url  特别提醒:jdbc:mysql//服务器地址/数据库名-->
<!--       value="jdbc:mysql://localhost/db1" 这个db1要改成你的数据库库名。-->
        <property name="url" value="jdbc:mysql://localhost/db1"></property>
<!--        连接数据库的用户名-->
        <property name="username" value="root"></property>
<!--        连接数据库的密码-->
        <property name="password" value="123456"></property>
    </bean>

<!--    2、配置JDBC模板-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--            默认必须使用数据源。-->
        <!--        ref引用上一个bean的对象。通俗的说:就是把前面一个Bean的实例注入到当前这个Bean中。-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!--    3、定义id为accountDao的Bean-->
    <bean id="accountDao" class="com.stx.chapter05.AccountDaoImpl">
<!--        将jdbcTemplate实例对象,注入到account实例中,然后就在Account存在,并被引用..-->
        <property name="jdbcTemplate" ref="jdbcTemplate"></property>
    </bean>

<!--    4、事务管理器,依赖于数据源。-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--       把数据库即mysql的数据控制权注入到事务管理器里面。-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
<!--    5、编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节。-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
<!--            name:*表示任意方法名称。-->
            <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
        </tx:attributes>
    </tx:advice>
<!--    6、编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式:execution(* com.stx.chapter05.*.*(..))-->
    <aop:config>
<!--        切入点-->
        <aop:pointcut id="txPointCut" expression="execution(* com.stx.chapter05.*.*(..))"/>
<!--        切面:将切入点与通知整合-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>
</beans>

 


http://www.niftyadmin.cn/n/4557279.html

相关文章

BZOJ 2342 [Shoi2011]双倍回文(manacher+堆+set)

题意 N<500000 题解 维护一个set可以用堆来解决。 1 #include<iostream>2 #include<cstring>3 #include<cstdio>4 #include<cmath>5 #include<algorithm>6 #include<set>7 #include<queue>8 using namespace std;9 const int N50…

c.k死了没.

||| over了 很神奇 别去猜测时间能够说明一切问题&#xff0e;

(9)Spring框架——MyBatis的学习

目录 一、概述 &#xff08;一&#xff09;项目准备工作 &#xff08;二&#xff09;项目结构描述 &#xff08;三&#xff09;具体作用概述 二、举例 &#xff08;一&#xff09;步骤 &#xff08;二&#xff09;实例 一、概述 &#xff08;一&#xff09;项目准备工作…

一个C++编程问题

而现在的方法是 按引用调用 (call by reference) 传递 即将实参复制给形参 如果去掉就编程 使用按值调用 (call by value) 来传递参数了 这样形参才能改变实参的值 这样实参的值不会被形参改变

HDU 2612 find a way 【双BFS】

<题目链接> 题目大意&#xff1a;两个人分别从地图中的Y 和 M出发&#xff0c;要共同在 处会面&#xff08;不止有一处&#xff09;&#xff0c;问这两个人所走距离和的最小值是多少。 解题分析&#xff1a; 就是对这两个点分别进行一次BFS&#xff0c;求出它们到每一个…

(10)Spring框架——MyBatis的学习之动态SQL

目录 一、描述 1、准备工作 2、总体思路 3、我出现的问题 二、步骤 1、根据项目结构建包&#xff0c;建类。 2、外部引入文件 三、实例 1、区别 一、描述 1、准备工作 &#xff08;1&#xff09;环境配置——相互作用 a.其中mybatis-config.xml&#xff08;配置数据…

(11)Spring框架——MyBatis的学习之动态SQL

目录 一、动态SQL的元素 二、实例 1、项目结构 2、建包建类 3、配置文件 一、动态SQL的元素 元素作用<if>是判断语句&#xff0c;当满足了条件就会执行标签里面的动态SQL <choose><when> <otherwise> <when>会进行多层判断&#xff0c;最后…

Go语言基础:method

我们在C语言中&#xff0c;struct中声明函数&#xff0c;而Go中则不能再struct中声明函数。而是采用另外一种形态存在&#xff0c;Go中叫method。 method的概念 method是附属在一个给定的类型上&#xff0c;语法和函数的声明语法几乎一样&#xff0c;只是再func后面增加了一个r…