1、Spring事务管理
-
什么是事务?
事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。 -
事务的特性:
原子性、隔离性、一致性、持久性 -
Spring的事务管理?
在实际开发中,操作数据库时都会涉及到事务管理问题,为此Spring提供了专门用于事务处理的API。Spring 的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。 -
Spring事务管理的方式:
编程式事务管理
声明式事务管理:xml方式和注解(Annotation)方式
2、实验
1、 实验目录
主要说明:
src/main/java/cn.edu.ujn.ch5 为代码
src/test/java/cn.edu.ujn.ch5 为测试代码
applicationContext.xml Spring配置文件
pom.xml maven配置文件
Account.java
IAccountDao.java 用户接口
AccountDaoImpl.java 用户接口的实现类
SpringTestJDBC.java 测试类
2、主要代码
Account.java
package cn.edu.ujn.ch5;
import org.springframework.stereotype.Component;
@Component
public class Account {
private Integer id; // 账户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;
}
}
IAccountDao.java 用户接口
package cn.edu.ujn.ch5;
import java.util.List;
public interface IAccountDao {
public int addAccount(Account account);
public List<Account> findAllAccount();
public void transfer(String outUser, String inUser, Double money);
}
AccountDaoImpl.java 用户接口的实现类
package cn.edu.ujn.ch5;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public int addAccount(Account account) {
// TODO Auto-generated method stub
String sql = "insert into account(username,balance) value(?,?)";
Object[] obj = new Object[] {account.getUsername(), account.getBalance()};
int num = this.jdbcTemplate.update(sql, obj);
return num;
}
public List<Account> findAllAccount() {
// TODO Auto-generated method stub
return null;
}
//需要封装事务的方法,加@Transactionl
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
// TODO Auto-generated method stub
this.jdbcTemplate.update("update account set balance = balance-? " + " where username=?", money,outUser);
int i=1/0; //这里会产生一个异常,在先减后加之间,如果不封装事务,
//会先减少,然后出现异常,然后不继续执行,如果此方法
//封装事务,则会在这个异常后回滚到运行这个方法之前的
//状态。避免了减完不加的情况。
this.jdbcTemplate.update("update account set balance = balance+? " + " where username=?", money,inUser);
}
}
SpringTestJDBC.java 测试类
package cn.edu.ujn.ch5;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:applicationContext.xml")
public class SpringTestJDBC {
@Autowired
private IAccountDao accountDao;
@Autowired
private Account account;
@Test
public void addTest() {
account.setUsername("张三");
account.setBalance(10000.00);
int i = accountDao.addAccount(account);
System.out.println("插入成功:"+i);
}
@Test
public void transferTest() {
accountDao.transfer("wang", "jia", 100.00);
System.out.println("转账成功!");
}
}
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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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/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">
<!-- 指定需要扫描的包,使注解生效 -->
<context:component-scan base-package="cn.edu.ujn" />
<bean id="dataSource" class= "org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--数据库驱动 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<!--连接数据库的url -->
<property name="url" value="jdbc:mysql://localhost:3306/java_ee?characterEncoding=utf-8" />
<!--"?characterEncoding=utf-8"让数据库可以输入中文-->
<!--连接数据库的用户名 -->
<property name="username" value="root" />
<!--连接数据库的密码 -->
<property name="password" value="" />
</bean>
<!-- 2配置JDBC模板 -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<!-- 默认必须使用数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注解方式 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- XML方式 -->
<!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* cn.edu.cn.ch5.*.*(..))" id="txPointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref=""txPointcut""/>
</aop:config> -->
</beans>