言成言成啊 | Kit Chen's Blog

Spring的事务控制及JdbcTemplate

发布于2021-04-05 03:04:24,更新于2021-04-22 01:51:14,标签:spring  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

目录

  1. Spring的IOC和DI
  2. Spring的AOP
  3. Spring的事务控制
  4. 源码

一、JdbcTemplate

1.1 概述

JdbcTemplate是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装。

Spring框架提供的工具类

  1. 关系型数据库
    • JdbcTemplate
    • HibernateTemplate
  2. 非关系型数据库
    • RedisTemplate
  3. 操作消息队列
    • JmsTemplate

JdbcTemplate的作用:它就是与数据库交互的,实现对表的CRUD操作

1.2 使用

简单使用

可以直接用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class JdbcTemplateDemo01 {
public static void main(String[] args) {
//准备数据源:Spring的内置数据源
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
ds.setUsername("root");
ds.setPassword("root");
//1.创建JdbcTemplate对象
JdbcTemplate jt=new JdbcTemplate();
jt.setDataSource(ds);
//2. 执行操作
jt.execute("insert into account(name,money)values('ccc',1000)");
}
}

Spring注解使用

Config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
@ComponentScan("top.meethigher.demo19")
@EnableAspectJAutoProxy
public class Config {
@Bean("ds")
public DataSource createDataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/spring?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
@Bean("jdbcTemplate")
public JdbcTemplate createJdbcTemplate(@Qualifier("ds") DataSource ds){
return new JdbcTemplate(ds);
}
}

Account

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Account implements Serializable {
private Integer id;
private String name;
private Float money;

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

public Integer getId() {
return id;
}

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

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Float getMoney() {
return money;
}

public void setMoney(Float money) {
this.money = money;
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class JdbcTemplateDemo02 {
public static void main(String[] args) {
AnnotationConfigApplicationContext aac = new AnnotationConfigApplicationContext(Config.class);
// JdbcTemplate jdbcTemplate = (JdbcTemplate) aac.getBean("jdbcTemplate");
JdbcTemplate jdbcTemplate = aac.getBean("jdbcTemplate", JdbcTemplate.class);
//插入
// jdbcTemplate.execute("insert into account(name,money)values('ddd',2222)");
//修改
// jdbcTemplate.update("update account set name=?,money=? where id=?","bbb",111,13);
//删除
// jdbcTemplate.update("delete from account where id=?",13);
//查询所有
// List<Account> query = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<>(Account.class));
// System.out.println(query);
//查询一个
// List<Account> query = jdbcTemplate.query("select * from account where id=?", new BeanPropertyRowMapper<>(Account.class), 1);
// System.out.println(query.get(0));
//查询总记录数
Long aLong = jdbcTemplate.queryForObject("select count(*) from account where money>?", Long.class, 1000);
System.out.println(aLong);
}
}

Spring与Dao的联合使用的两种方式

使用注解的dao层来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Component("accoundDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Account findAccountById(Integer accountId) {
List<Account> query = jdbcTemplate.query("select * from account where id=?", new BeanPropertyRowMapper<>(Account.class), accountId);
if(query.isEmpty()){
return null;
}
return query.get(0);
}

@Override
public Account findAccountByName(String name) {
List<Account> query = jdbcTemplate.query("select * from account where name=?", new BeanPropertyRowMapper<>(Account.class), name);
if(query.isEmpty()){
return null;
}
if(query.size()>1){
throw new RuntimeException("结果不唯一");
}
return query.get(0);
}

@Override
public void updateAccount(Account account) {
jdbcTemplate.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
}
}

使用xml的dao层来实现

但是如果有很多个dao的话,就会有重复代码了,那么如何解决?

我们可以通过创建一个dao的共有父类,让其他子类继承

而spring中,提供了这种个父类JdbcDaoSupport

AccountDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
@Override
public Account findAccountById(Integer accountId) {
List<Account> query = super.getJdbcTemplate().query("select * from account where id=?", new BeanPropertyRowMapper<>(Account.class), accountId);
if(query.isEmpty()){
return null;
}
return query.get(0);
}

@Override
public Account findAccountByName(String name) {
List<Account> query = super.getJdbcTemplate().query("select * from account where name=?", new BeanPropertyRowMapper<>(Account.class), name);
if(query.isEmpty()){
return null;
}
if(query.size()>1){
throw new RuntimeException("结果不唯一");
}
return query.get(0);
}

@Override
public void updateAccount(Account account) {
super.getJdbcTemplate().update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
}
}

spring.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="accountDao" class="top.meethigher.demo20.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="ds"/>
</bean>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/spring?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
</beans>

测试类

1
2
3
4
5
6
7
8
9
public class JdbcTemplateDemo03 {
public static void main(String[] args) {
ClassPathXmlApplicationContext aac = new ClassPathXmlApplicationContext("spring.xml");
AccountDaoImpl accoundDao = aac.getBean("accountDao", AccountDaoImpl.class);
System.out.println(accoundDao.findAccountById(1));
// System.out.println(accoundDao.findAccountByName("水冰儿"));
System.out.println(accoundDao.findAccountByName("小舞"));
}
}

二、事务控制

2.1 转账案例再次优化

如果使用环绕通知,只需要修改如下即可。会自动将impl包下的类作为切入点,进行增强

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
@Component("tsManager")
@Aspect
public class TransactionManager {
@Autowired
private ConnectionUtils connectionUtils;
@Pointcut("execution(* top.meethigher.demo21.service.impl.*.*(..))")
private void pt(){}

/**
* 开启手动提交事务
*/
// @Before("pt()")
public void beginTransaction(){
try {
connectionUtils.getThreadConnection().setAutoCommit(false);
System.out.println("开启手动提交事务");
} catch (SQLException e) {
e.printStackTrace();
}
}

/**
* 提交事务
*/
// @AfterReturning("pt()")
public void commitTransaction(){
try {
connectionUtils.getThreadConnection().commit();
System.out.println("提交事务");
} catch (SQLException e) {
e.printStackTrace();
}
}

/**
* 回滚事务
*/
// @AfterThrowing("pt()")
public void rollbackTransaction(){
try {
connectionUtils.getThreadConnection().rollback();
System.out.println("回滚事务");
} catch (SQLException e) {
e.printStackTrace();
}
}

/**
* 释放连接
*/
// @After("pt()")
public void release(){
try {
connectionUtils.getThreadConnection().close();//归还连接
System.out.println("归还连接");
} catch (SQLException e) {
e.printStackTrace();
}
}

/**
* 环绕通知实现增强
* @param proceedingJoinPoint
* @return
*/
@Around("pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint){
Object returnValue=null;
try{
beginTransaction();
System.out.println("前置通知->开启事务");
returnValue = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
commitTransaction();
System.out.println("后置通知->提交事务");
return returnValue;
}catch (Throwable t){
rollbackTransaction();
System.out.println("异常通知->回滚事务");
throw new RuntimeException(t);
}finally {
release();
System.out.println("最终通知->释放连接");
}
}
}

此时我们就需要思考了,这是使用QueryRunner实现的,如果是JdbcTemplate,如何实现事务控制呢?

2.2 spring声明式事务

基于xml的声明式事务

步骤

  1. 配置事务管理器

    • spring提供的DataSourceTransactionManager
  2. 配置事务通知

    • 需要导入事务的约束。官方文档DataAccess,搜索xmlns:tx(同时也需要aop的)
    • 使用tx:advice标签配置事务通知
      • id:事务通知的唯一标志
      • transaction-manager:给事务通知提供一个事务管理器引用
  3. 配置aop中的通用切入点表达式:aop:pointcut

  4. 建立事务通知和切入点表达式的对应关系:aop:advisor

  5. 配置事务的属性:在tx:advice的内部下的tx:method

    • name:方法名称。可以使用通配符*表示所有。如果名称规范的话,findxxx,像jpa那样,可以这么统配find**find*,后者优先级更高

    • isolation:用于指定事务的隔离级别,默认级别DEFAULT,表示使用数据库的默认隔离级别

    • no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚;产生其他异常时,事务回滚。没有默认值,表示任何异常都回滚。

    • rollback-for:用于指定一个异常,当产生该异常时,事务回滚;产生其他异常时,不回滚。没有默认值,表示任何异常都回滚

    • propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改时选择。查询方法可以选择SUPPORTS

    • read-only:用于指定事务事务是否只读,只有查询方法才能设置为true,默认值是false,表示读写

    • timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="accountDao" class="top.meethigher.demo21.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="ds"/>
</bean>
<bean id="accountService" class="top.meethigher.demo21.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
</bean>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/spring?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--配置事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务属性-->
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--配置aop-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* top.meethigher.demo21.service.impl.*.*(..))"/>
<!--建立切入点表达式和事务通知的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
</beans>

AccountDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {

@Override
public Account findAccountByName(String name) {
List<Account> query = super.getJdbcTemplate().query(
"select * from account where name=?",
new BeanPropertyRowMapper<>(Account.class),
name);
if (!query.isEmpty()) {
return query.get(0);
}
return null;
}

@Override
public void transfer(String sourceName, String targetName, Float money) {
Account account1 = findAccountByName(sourceName);
Account account2 = findAccountByName(targetName);
account1.setMoney(account1.getMoney()-money);
account2.setMoney(account2.getMoney()+money);
update(account1);
int a=2/0;
update(account2);
}

@Override
public void update(Account account) {
super.getJdbcTemplate().update(
"update account set money=? where id=?",
account.getMoney(), account.getId()
);
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class Test21 {
@Autowired
private AccountService accountService;

@Test
public void testTransfer() {
accountService.transfer("白沉香","小舞",500f);
}
}

基于注解与xml的声明式事务

步骤

  1. 配置事务管理器
  2. 开启spring对注解事务的支持
  3. 在需要事务支持的地方,使用@Transactional注解

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="top.meethigher.demo22"/>
<bean id="accountDao" class="top.meethigher.demo22.dao.impl.AccountDaoImpl"/>
<bean id="accountService" class="top.meethigher.demo22.service.impl.AccountServiceImpl"/>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/spring?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds"/>
</bean>
<!--配置事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<!--开启spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

AccountDaoImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Repository("accountDao")
@Transactional(readOnly = true)//配置为只读事务,也就是查询
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;

@Override
public Account findAccountByName(String name) {
List<Account> query = jdbcTemplate.query(
"select * from account where name=?",
new BeanPropertyRowMapper<>(Account.class),
name);
if (!query.isEmpty()) {
return query.get(0);
}
return null;
}

@Transactional(readOnly = false)//修改为读写事务,也就是增删改
@Override
public void transfer(String sourceName, String targetName, Float money) {
Account account1 = findAccountByName(sourceName);
Account account2 = findAccountByName(targetName);
account1.setMoney(account1.getMoney()-money);
account2.setMoney(account2.getMoney()+money);
update(account1);
int a=2/0;
update(account2);
}

@Override
public void update(Account account) {
jdbcTemplate.update(
"update account set money=? where id=?",
account.getMoney(), account.getId()
);
}
}

AccountServiceImpl

1
2
3
4
5
6
7
8
9
10
@Service("accountService")
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;

@Override
public void transfer(String sourceName, String targetName, float money) {
accountDao.transfer(sourceName,targetName,money);
}
}

测试类

1
2
3
4
5
6
7
8
9
10
11
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring.xml")
public class Test22 {
@Autowired
private AccountService accountService;

@Test
public void testTransfer() {
accountService.transfer("白沉香","小舞",500f);
}
}

基于注解的声明式事务

替代xml中的开启spring对注解事务的支持

  • @EnableTransactionManagement

jdbc.properties

1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
u=root
pw=1050121804

配置类

JdbcConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {
@Value("${u}")
private String USER;
@Value("${pw}")
private String PASS;
@Value("${driver}")
private String DRIVER;
@Value("${url}")
private String URL;
@Bean("jdbcTemplate")
public JdbcTemplate createJdbcTemplate(@Qualifier("ds") DataSource ds){
return new JdbcTemplate(ds);
}
@Bean("ds")
public DataSource createDataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setUsername(USER);
ds.setPassword(PASS);
ds.setDriverClassName(DRIVER);
ds.setUrl(URL);
return ds;
}
}

TransactionManagerConfig

1
2
3
4
5
6
7
@Configuration
public class TransactionManagerConfig {
@Bean("transactionManager")
public PlatformTransactionManager createTransactionManager(@Qualifier("ds") DataSource ds){
return new DataSourceTransactionManager(ds);
}
}

SpringConfig

1
2
3
4
5
6
@Configuration
@ComponentScan(basePackages = "top.meethigher.demo23")
@Import({JdbcConfig.class,TransactionManagerConfig.class})
@EnableTransactionManagement//开启对事务的支持
public class SpringConfig {
}

测试类

1
2
3
4
5
6
7
8
9
10
11
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Test23 {
@Autowired
private AccountService accountService;

@Test
public void testTransfer() {
accountService.transfer("白沉香","小舞",500f);
}
}

其他的跟上一节的一样。

2.3 spring编程式事务

需要在配置里添加事务模板对象,用于对指定方法进行添加事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="top.meethigher.demo24"/>
<bean id="accountDao" class="top.meethigher.demo24.dao.impl.AccountDaoImpl">
<property name="dataSource" ref="ds"/>
</bean>
<bean id="accountService" class="top.meethigher.demo24.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/spring?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1050121804"/>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<!--事务模板对象-->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
</beans>

其他类都一样,唯一不同的是对要方法进行添加事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class AccountServiceImpl implements AccountService {
private TransactionTemplate transactionTemplate;
private AccountDao accountDao;

public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}

public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}

@Override
public void transfer(String sourceName, String targetName, float money) {
transactionTemplate.execute(new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
accountDao.transfer(sourceName, targetName, money);
return null;
}
});

}
}

缺点:让方法实现事务功能时,都需要写这么多,太麻烦了。还是注解的声明式事务用的多一点,只需要配置事务并添加@Transaction注解即可。

发布:2021-04-05 03:04:24
修改:2021-04-22 01:51:14
链接:https://meethigher.top/blog/2021/spring3/
标签:spring 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏