1.spring事务是基于aop思想实现的,即aop事务
- spring封装了事务管理代码
- 事务操作:打开事务,提交事务,回滚事务
- 事务操作对象:因为在不同平台,操作事务的代码各不相同.spring提供了一个接口,PlatformTransactionManager 接口
- DataSourceTransactionManager
- HibernateTransitionmanager
- 注意:在spring事务管理.最为核心的对象就是TransactionManager对象
- spring管理事务的属性介绍
1.事务得隔离级别:
1 读未提交
2 读已提交
4 可重复读
8 串行化2,是否只读
true 只读
false 可操作3,事务的传播行为
2.xml实现aop事务
(需要先了解spring aop面向切面编程)
1.在spring配置文件中配置通知:
<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象 -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事物通知 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--以方法为单位,指定方法应用什么事务属性 -->
<!--isolation隔离级别 propagation传播行为 read-only是否只读 -->
<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="append*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="edit*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="repair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="delAndRepair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="search*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="datagrid*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
2.配置将通知织入目标
<!-- 配置织入 -->
<aop:config>
<!-- 将service层需要事务的方法作为切点 -->
<aop:pointcut id="transactionPointcut" expression="execution(* com.sj.service.imp.*DerviceImp.*(..))" />
<!--配置切面 通知+切点-->
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
</aop:config>
3.书写dao以及实现dao
public interface UserDao {
void save(User u);
void delete(Integer id);
void update(User u);
User getUser(Integer id);
List<User> getAllUser();
void updateAddMoney(Integer id,Double money);
void updatereduceMoney(Integer id,Double money);
}
public class UserDaoImp extends JdbcDaoSupport implements UserDao {
@Override
public void save(User u) {
String sql = "insert into user (name,money) values(?,?)";
super.getJdbcTemplate().update(sql, u.getName(), u.getMoney());
}
@Override
public void delete(Integer id) {
String sql = "delete from user where id = ?";
super.getJdbcTemplate().update(sql, id);
}
@Override
public void update(User u) {
String sql = "update user set name = ? where id = ? ";
super.getJdbcTemplate().update(sql, u.getName(), u.getId());
}
@Override
public User getUser(Integer id) {
String sql = "select * from user where id = ?";
User u = super.getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
u.setMoney(rs.getDouble("money"));
return u;
}
}, id);
return u;
}
@Override
public List<User> getAllUser() {
String sql = "select * from user ";
List<User> u = super.getJdbcTemplate().query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int arg1) throws SQLException {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
u.setMoney(rs.getDouble("money"));
return u;
}
});
return u;
}
@Override
public void updateAddMoney(Integer id, Double money) {
String sql = "update user set money=money + ? where id=?";
super.getJdbcTemplate().update(sql, money, id);
}
@Override
public void updatereduceMoney(Integer id, Double money) {
String sql = "update user set money=money - ? where id=?";
super.getJdbcTemplate().update(sql, money, id);
}
}
3.书写service以及实现
扫描二维码关注公众号,回复:
4861949 查看本文章
public interface UserService {
void updateMoney(Integer from, Integer to, Double money);
void updateMoney2(Integer from, Integer to, Double money);
public User getUser(Integer id);
}
public class UserServiceImp implements UserService {
private UserDao userDao;
@Override
public User getUser(Integer id) {
User u = userDao.getUser(id);
return u;
}
// 转钱
@Override
public void updateMoney(Integer from, Integer to, Double money) {
userDao.updatereduceMoney(from, money);
userDao.updateAddMoney(to, money);
}
// 转钱 异常
@Override
public void updateMoney2(Integer from, Integer to, Double money) {
userDao.updatereduceMoney(from, money);
// 模拟异常
int s = 1;
int i = s / 0;
userDao.updateAddMoney(to, money);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
4.注入dao,service到spring
<!-- 引入外部文文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置连接池 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Dao -->
<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- Service -->
<bean name="userService" class="com.sj.service.imp.UserServiceImp">
<property name="userDao" ref="userDao"></property>
</bean>
4.完整spirng配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 引入外部文文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置连接池 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Dao -->
<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- Service -->
<bean name="userService" class="com.sj.service.imp.UserServiceImp">
<property name="userDao" ref="userDao"></property>
</bean>
<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象 -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置事物通知 -->
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--以方法为单位,指定方法应用什么事务属性 -->
<!--isolation隔离级别 propagation传播行为 read-only是否只读 -->
<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="append*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
<tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="edit*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
<tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="repair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="delAndRepair" isolation="DEFAULT" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="search*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
<tx:method name="datagrid*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置织入 -->
<aop:config>
<!--配置切点 表达式 -->
<!-- 将service层需要事务的方法作为切点 -->
<aop:pointcut id="transactionPointcut" expression="execution(* com.sj.service.imp.*DerviceImp.*(..))" />
<!--配置切面 通知+切点-->
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
</aop:config>
</beans>
5.Test测试
public class SpringTest {
@Test
public void run3() {
// 转钱
ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserServiceImp service = (UserServiceImp) app.getBean("userService");
service.updateMoney(2, 1, 100d);
}
@Test
public void run4() {
// 转钱(异常)
ApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
UserServiceImp service = (UserServiceImp) app.getBean("userService");
service.updateMoney2(2, 1, 100d);
}
}
1.执行run3,转账成功
2.执行run4(执行应该转账失败,回滚事务)
如果未配置事务结果是(执行减少自己账户前后出现异常,导致对方账户未收到)
配置事务后:
3.注解事务:就很简单了直接添加
<tx:annotation-driven transaction-manager="transactionManager" />
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
<!-- 引入外部文文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置连接池 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- Dao -->
<bean name="userDao" class="com.sj.dao.imp.UserDaoImp">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- Service -->
<bean name="userService" class="com.sj.service.imp.UserServiceImp">
<property name="userDao" ref="userDao"></property>
</bean>
<!--在spring中玩事务管理.最为核心的对象就是TransactionManager对象 -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
2.在service用注解实现事务
//类注解给所有方法添加事务,可以直接在方法覆盖类注解事务
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = true)
public class UserServiceImp implements UserService {
private UserDao userDao;
public User getUser(Integer id) {
User u = userDao.getUser(id);
return u;
}
// 转钱,将只读改为false
@Override
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
public void updateMoney(Integer from, Integer to, Double money) {
userDao.updatereduceMoney(from, money);
userDao.updateAddMoney(to, money);
}
// 转钱 异常,将只读改为false
@Override
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, readOnly = false)
public void updateMoney2(Integer from, Integer to, Double money) {
userDao.updatereduceMoney(from, money);
// 模拟异常
int s = 1;
int i = s / 0;
userDao.updateAddMoney(to, money);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
注解事务就ok