spring 事务管理的简单配置
1:事务的优点
事务管理对平时的业务逻辑的健壮性帮助很大,它保证了一个动作的原子性
本例中主要体现在,购票或者购书中,业务逻辑如下:
1:根据商品的ID查询该商品的价格,
2:根据商品的价格去扣除用户的余额,但余额不足时,主动抛出异常
3:当用户付款成功后,扣除商品库存,单库存不足时,主动抛出异常
当3个步骤都操作成功后,数据库才会真正的持久化,即数据发生改变
项目路径保存在 D:\海同\spring\9.14\9.14 中
额外jar包:
aopalliance.jar 和 aspectjweaver.jar 和 spring-aspects-4.2.0.RELEASE.jar 切面必须包
c3p0-0.9.2.1.jar 和 commons-logging-1.1.1.jar 和 mysql-connector-java-5.1.7-bin.jar 数据库必须包
2:注解配置事务流程
比较方便
Repository层接口:
public interface GoodDao { //查找商品价格 public int findPriceById(String id); //修改商品数量每次-1 public void updateGoods(String id); //修改用户的余额 public void updateBalance(String username,int price); }
Repository层实体:
/声明并装配到spring容器中去 @Repository("goodDao") public class GoodDaoImpl implements GoodDao { // 配置属性,从spring容器中取出 JdbcTemplate 对象 @Resource(name = "jdbcTemplate") private JdbcTemplate jdbcTemplate; @Override public int findPriceById(String id) { String sql = "select price from goods where id = ?"; // 返回值为Integer的类类型 return jdbcTemplate.queryForObject(sql,Integer.class,id); } @Override public void updateGoods(String id) { String select = "SELECT NUMBER FROM good_numbers WHERE id = ?"; int number = jdbcTemplate.queryForObject(select,Integer.class,id); if (number < 1){
// 该异常为自定义异常,仅继承了 RunTimeException 不贴上代码 throw new GoodException("商品数量不足"); } String sql = "update good_numbers set number = number-1 where id = ?"; jdbcTemplate.update(sql,id); } @Override public void updateBalance(String username, int price) { String select = "SELECT balance FROM users WHERE username = ?"; int balance = jdbcTemplate.queryForObject(select,Integer.class,username); if (balance < price){
// 该异常为自定义异常,仅继承了 RunTimeException 不贴上代码
throw new UserException("用户余额不足"); }
String sql = "update users set balance = balance - ? where username = ?";
jdbcTemplate.update(sql,price,username);
}
}
Service层的接口和实现:
//接口 public interface GoodService { public void buyGood(String username,String id); } //实现类 @Service("goodService") public class GoodServiceImpl implements GoodService { @Resource(name = "goodDao") private GoodDao goodDao; @Transactional @Override public void buyGood(String username, String id) { int price = goodDao.findPriceById(id); goodDao.updateGoods(id); goodDao.updateBalance(username,price); } }
测试类
public class TestGoodService { private GoodService goodService; @Test public void test(){ ApplicationContext applicationContext =new ClassPathXmlApplicationContext("application.xml"); this.goodService = (GoodService) applicationContext.getBean("goodService"); goodService.buyGood("aa","1"); } }
XML的配置方式:
xml中仅仅是在配置文件中不同,和实体类中取出了所有的注解,故,只将xml文件帖出:
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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" 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-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--读取配置文件--> <context:property-placeholder location="classpath:db.property"></context:property-placeholder> <!--加载数据源--> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--注入spring中的JdbcTemplate--> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!--注入repository--> <bean id="goodDao" class="com.yuwenhui.jdbc.xml.repository.GoodDaoImpl"> <property name="jdbcTemplate" ref="jdbcTemplate"></property> </bean> <!--注入Service--> <bean id="goodService" class="com.yuwenhui.jdbc.xml.service.GoodServiceImpl"> <property name="goodDao" ref="goodDao"></property> </bean> <!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务属性--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 配置aop --> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.yuwenhui.jdbc.xml.service.GoodServiceImpl.* (..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" id="aopAdvisor"/> </aop:config> </beans>
配置文件 db.propertys
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql:///spring jdbc.user=root jdbc.password=123456