就像前面AOP等部分介绍的,spring在实现AOP时提供了注解和xml配置两种方式。同样,配置事务管理,也可以使用xml文件配置。
这里我们将前面的例子重新复制一份,在tx2包中。
我们把注解全去掉,这里挑一个吧。
package com.happBKs.spring.tx2;
public interface BookShopDao {
//根据书号获取书的单价
public int findBookPriceIsdn(String isbn);
//更新书的库存,使得书号对应的库存-1
public void updateBookStock(String isbn);
//更新用户的账户余额:使得相应username记录的balance-price
public void updateUserAccount(String username,int price);
}
package com.happBKs.spring.tx2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
public class BookShopDaoImpl implements BookShopDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public int findBookPriceIsdn(String isbn) {
// TODO Auto-generated method stub
String sql="select price from book where isbn = ?";
return jdbcTemplate.queryForObject(sql, Integer.class,isbn);
}
public void updateBookStock(String isbn) {
String sql0="select stock from book_stock where isbn = ?";
int stock=jdbcTemplate.queryForObject(sql0,Integer.class, isbn);
if(stock==0)
{
throw new RuntimeException("库存不足!");
}
// TODO Auto-generated method stub
String sql="update book_stock set stock = stock-1 where isbn = ?";
jdbcTemplate.update(sql,isbn);
}
public void updateUserAccount(String username, int price) {
String sql0="select balance from account where username = ?";
int balance=jdbcTemplate.queryForObject(sql0,Integer.class, username);
if(balance<price)
{
throw new RuntimeException("余额不足!");
}
// TODO Auto-generated method stub
String sql="update account set balance = balance - ? where username = ?";
jdbcTemplate.update(sql,price,username);
}
}
最重要的来了,配置文件怎么写?基本步骤是什么?请看:(本文出自:http://my.oschina.net/happyBKs/blog/513453)
<?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/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
<!-- 自动扫描的包 -->
<context:component-scan base-package="com.happBKs.spring.jdbcSpring"></context:component-scan>
<context:component-scan base-package="com.happBKs.spring.tx"></context:component-scan>
<!-- 导入资源文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 配置c3p0数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="initialPoolSize" value="${jdbc.initPoolSize}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean>
<!-- 配置jdbc模板类 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置bean -->
<bean id="bookShopDao" class="com.happBKs.spring.tx2.BookShopDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id="bookShopService" class="com.happBKs.spring.tx2.BookShopServiceImpl">
<property name="bookShopDao" ref="bookShopDao"></property>
</bean>
<bean id="cashier" class="com.happBKs.spring.tx2.CashierImpl">
<property name="bookShopService" ref="bookShopService"></property>
</bean>
<!-- 1. 配置事务管理器。以后集成Hibernate、Mybatis需要配置不同的事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2. 配置事务属性。传播行为、隔离级别、只读、超时时间回滚-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="purchase" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- 2. 配置事务切入点。并把事务切入点与事务属性关联起来。-->
<aop:config>
<aop:pointcut expression="execution(* com.happBKs.spring.tx2.BookShopDaoImpl.*(..))" id="txPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
测试程序:
package com.happBKs.spring.tx2;
import java.util.Arrays;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TransactionTest {
private ApplicationContext ctx=null;
private BookShopDao bookShopDao;
private BookShopService bookShopService;
private Cashier cashier=null;
{
ctx=new ClassPathXmlApplicationContext("applicationContext_xml.xml");
bookShopDao=ctx.getBean(BookShopDao.class);
bookShopService=ctx.getBean(BookShopService.class);
cashier=ctx.getBean(Cashier.class);
}
@Test
public void test1(){
System.out.println(bookShopDao.findBookPriceIsdn("1001"));
}
@Test
public void test2(){
bookShopDao.updateBookStock("1001");
}
@Test
public void test3(){
bookShopDao.updateUserAccount("HappyBKs", 100);
}
}