spring事务全注解开发

对于 @Transactional 注解,Spring 会根据目标对象是否实现了接口来决定使用哪种代理方式。如果目标对象实现了接口,Spring 会使用 JDK 动态代理;否则,它会使用 CGLIB 代理。
因此,@Transactional 注解的实现并不完全基于 JDK 接口代理,它还支持基于类的代理(通过 CGLIB)。具体使用哪种代理方式取决于目标对象是否实现了接口。

  • 引用的包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.1.8</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
  • 定义接口
package com.powernode.bank.dao;
import com.powernode.bank.pojo.Account;
public interface AccountDao {
//根据账号查询账户信息
Account selectByActno(String actno);
//更新账户信息
int update(Account act);
//保存账户信息
int insert(Account act);
}
  • 定义接口实现类
package com.powernode.bank.dao.impl;
import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import jakarta.annotation.Resource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl implements AccountDao {
@Resource
private JdbcTemplate jdbcTemplate;
@Override
public Account selectByActno(String actno) {
String sql = "select actno,balance from t_act where actno = ?";
Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Account.class), actno);
System.out.println("笑"+account);
return account;
}
@Override
public int update(Account act) {
String sql = "update t_act set balance = ? where actno = ?";
int update = jdbcTemplate.update(sql, act.getBalance(), act.getActno());
return update;
}
@Override
public int insert(Account act) {
String sql = "insert into t_act values(?,?)";
return jdbcTemplate.update(sql,act.getActno(),act.getBalance());
}
}
  • 实体类
package com.powernode.bank.pojo;
public class Account {
private String actno;
private Double balance;
public Account() {
}
public Account(String actno, Double balance) {
this.actno = actno;
this.balance = balance;
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"actno='" + actno + '\'' +
", balance=" + balance +
'}';
}
}
  • 定义Service
package com.powernode.bank.service;
import com.powernode.bank.pojo.Account;
public interface AccountService {
void transfer(String fromActno, String toActno, double money);
void save(Account act);
}
  • 定义Service实现类
package com.powernode.bank.service.impl;
import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import com.powernode.bank.service.AccountService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
@Service
public class AccountServiceImpl implements AccountService {
@Resource
private AccountDao accountDao;
//控制事务
@Override
@Transactional
public void transfer(String fromActno, String toActno, double money) {
//查询余额
Account fromAct = accountDao.selectByActno(fromActno);
if (fromAct.getBalance() < money){
throw new RuntimeException("余额不足!!");
}
//余额充足
Account toAct = accountDao.selectByActno(toActno);
//将内存中两个对象的余额先修改
fromAct.setBalance(fromAct.getBalance() - money);
toAct.setBalance(toAct.getBalance() + money);
//数据库更新
int count = accountDao.update(fromAct);
//模拟异常
/* String s = null;
s.toString();*/
count += accountDao.update(toAct);
if (count !=2){
throw new RuntimeException("转账失败,联系银行");
}
}
@Resource(name = "accountServiceImpl2")
private AccountService accountService;
@Override
@Transactional(propagation = Propagation.REQUIRED)
public void save(Account act) {
//这里调用dao的insert方法
accountDao.insert(act);//保存act-003账户
//创建账户对象
Account act2 = new Account("act-004", 1000.0);
try{
accountService.save(act2); //保存act-004账户
}catch (Exception e){
}
}
}
  • 编辑注解配置类
package com.powernode.bank.service;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
@Configuration
@ComponentScan(value = {"com.powernode.bank"})
@EnableTransactionManagement //开启事务注解
public class Spring6Config {
//
@Bean(name = {"druidDataSource2"})
public DruidDataSource getDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
druidDataSource.setUrl("jdbc:mysql://192.168.1.41:3306/test");
druidDataSource.setUsername("root");
druidDataSource.setPassword("Abc123***");
return druidDataSource;
}
@Bean(name = "jdbcTemplate")
//spring在调用这个方法时会自动传递过来druidDataSource对象
public JdbcTemplate getJdbcTemplate(DataSource druidDataSource2){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(druidDataSource2);
return jdbcTemplate;
}
@Bean(name = "txManager")
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource druidDataSource2){
DataSourceTransactionManager txManager = new DataSourceTransactionManager();
txManager.setDataSource(druidDataSource2);
return txManager;
}
}
  • 测试,此处没有用service中的save方法
@Test
public void testNoXML(){
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Spring6Config.class);
AccountService accountServiceImpl = annotationConfigApplicationContext.getBean("accountServiceImpl", AccountService.class);
accountServiceImpl.transfer("act-001","act-002",10000);
System.out.println("转账成功");
}
posted @   文采杰出  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示