spring声明式事务配置

时间:2021-09-13 16:37:21

1.导入jar包

spring声明式事务配置

2.数据库配置文件jdbc.properties

jdbc.user=root
jdbc.password=123
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///spring

3.spring-bookstore.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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
	">
	
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<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="driverClass" value="${jdbc.driverClass}"></property>
	<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<context:component-scan base-package="com.neu.spring"></context:component-scan>

	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:annotation-driven transaction-manager="txManager"/>
	
</beans>

4.Dao层接口及实现类

public interface BookStoreDao {

	public float findPriceByIsbn(String isbn);
	
	public void userCountdel(String isbn,int userId);
	
	public void bookRemain(String isbn);
}


@Repository("bookStoreDao")
public class BookStoreDaoImpl implements BookStoreDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;
	
	/**
	 * 根据书的编号isbn查询书的库存
	 */
	@Override
	public void bookRemain(String isbn)   {
		String sql3 = "SELECT remain FROM book WHERE isbn=?";
		int remain = jdbcTemplate.queryForObject(sql3, Integer.class, isbn);
		if(remain<1)
				{
			throw new CountException("库存余额不足!!");
				}
		String sql = "UPDATE  BOOK SET remain=remain-1 WHERE isbn=?";
		jdbcTemplate.update(sql, isbn);
	}

	/**
	 * 根据书的编号和用户id,更新用户账户
	 */
	@Override
	public void userCountdel(String isbn, int userId){
		float price = findPriceByIsbn(isbn);
		String sql = "UPDATE  usercounter SET counter=counter-"+price+" WHERE userId=?";
		String sql2 = "SELECT counter FROM usercounter WHERE userId=?";
		float counter = jdbcTemplate.queryForObject(sql2, Float.class, userId);
		if(counter<price)
				throw new CountException("用户余额不足!!");
		jdbcTemplate.update(sql,userId);
	}

	/**
	 * 根据书的编号查询书的价格
	 */
	@Override
	public float findPriceByIsbn(String isbn) {
		
		String sql = "SELECT price FROM book WHERE isbn=?";
		float price = jdbcTemplate.queryForObject(sql, Float.class,isbn);
		return price;
	}

	
}

5.Service层接口和实现类

public interface BookService {

	public void purchase(int userId,String isbn);
}


@Service("bookService")
public class BookServiceImpl implements BookService {

	@Autowired
	private BookStoreDao bookStoreDao;
	
	@Transactional
	@Override
	public void purchase(int userId, String isbn) {
		//1.获取书的单价
		float price = bookStoreDao.findPriceByIsbn(isbn);
		//2.更新库存
		bookStoreDao.bookRemain(isbn);
		//3.更新用户账户
		bookStoreDao.userCountdel(isbn, userId);
		
		System.out.println("购买信息:");
		System.out.println("userId:"+userId+"---isbn:"+isbn);
		
		
	}

}

6.mysql无法检测书的库存和用户账户是否有效,需要手动抛出异常,定义异常类CountException

public class CountException extends RuntimeException {

	private static final long serialVersionUID = 1L;
	
	public CountException(String string) {
		super(string);
	}
}

7.测试代码

public class BookStoreTest {

	private ApplicationContext ctx = null;
	private BookService bookService = null;

	@Test
	public void testService(){
		ctx = new ClassPathXmlApplicationContext("spring-bookstore.xml");
		bookService = (BookService) ctx.getBean("bookService");
		bookService.purchase(2018, "1001");

	}
}

注:如果采用xml配置文件方式声明事务,只需将注解去掉,实体类中生成对应的set方法,修改配置文件如下:

<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	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/aop 
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
	">
	
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<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="driverClass" value="${jdbc.driverClass}"></property>
	<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
	</bean>
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean id="bookService" class="com.neu.spring.bookstore.xml.BookServiceImpl">
		<property name="bookStoreDao" ref="bookStoreDao"></property>
	</bean>
	<bean id="bookStoreDao" class="com.neu.spring.bookstore.xml.BookStoreDaoImpl">
		<property name="jdbcTemplate" ref="jdbcTemplate"></property>
	</bean>

	<!--配置事务管理器  -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- 配置事务属性 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<!-- 根据方法名指定事务属性 -->
			<tx:method name="purchase" propagation="REQUIRED"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="*"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 配置切点,并将切点与事务属性联系起来 -->
	<aop:config >
		<aop:pointcut expression="execution(public void com.neu.spring.bookstore.xml.BookServiceImpl.purchase(..))" id="pointCut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
	</aop:config>
</beans>