Spring声明式事务配置使用详解
什么是事务
事务是一组完整的业务操作,这些操作作为一个原子单元,要么全部成功,要么全部失败回滚,保证数据库中的数据一致性。
声明式事务的优点
Spring框架提供的声明式事务管理有以下几个好处:
-
代码简洁:通过使用声明式事务管理,Spring框架可以将所有的数据库事务处理的代码都放在配置文件中,这样就不需要在业务逻辑代码中手动控制事务的开启、提交或回滚事务的操作。
-
不受编程语言的限制:不管是Java还是其他任何支持AOP的编程语言,都可以使用Spring框架提供的声明式事务管理服务。这就意味着,只要是符合AOP的编程语言,都可以使用Spring框架提供的事务管理服务。
-
无代码侵入:使用声明式事务管理的好处之一是它不会对业务逻辑产生任何影响,因此,业务逻辑代码与事务管理的代码可以很好地分离。在这种情况下,业务逻辑代码可以集中在处理业务逻辑方面,而事务管理的代码可以集中在单独的配置文件中。
Spring声明式事务配置
Spring提供了两种方式实现声明式事务:
-
基于XML的声明式事务:该方式使用XML配置文件来配置声明式事务。
-
基于注解的声明式事务:该方式使用注解来配置声明式事务。
本文将介绍基于XML的声明式事务配置。
配置Spring声明式事务
配置事务管理器
在使用Spring声明式事务之前,必须先配置事务管理器,配置方式如下:
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
其中,transactionManager
是事务管理器的id,class
指定了使用的事务管理器类,这里使用的是DataSourceTransactionManager
类,这是一个基于DataSource的事务管理器,property
设置了dataSource属性,这里的dataSource是数据源的id,我们需要在该配置文件中提前定义。
配置数据源
在配置事务管理器时,需要指定使用的数据源,因此,需要在配置文件中提前配置数据源。数据源的配置方式因你所使用的具体数据源而异。在这里,我们演示使用Apache的Commons DBCP数据源的配置方式。以下是数据源配置的一些示例代码:
<!--数据库驱动-->
<bean id="driverManagerDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC&useSSL=false" />
<property name="username" value="myusername" />
<property name="password" value="mypassword" />
<property name="initialSize" value="5" /> <!--初始化连接数-->
<property name="maxIdle" value="10" /> <!--最大空闲连接-->
<property name="maxTotal" value="100" /> <!--最大连接数量-->
<property name="removeAbandonedOnBorrow" value="true" /> <!--连接过期是否自动回收-->
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="driverManagerDataSource"/>
</bean>
在上面的代码中,我们首先定义了一个Commons DBCP数据源,并指定了驱动类、URL、用户名和密码等参数。该数据源配置完成后,使用org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
类包装数据源,将数据源设置为"targetDataSource"
属性。
配置DAO
DAO层是访问数据库的一个封装层,需要在DAO中调用通过事务提交的代码。因此,在DAO中,必须使用Spring提供的JdbcTemplate
类来使用Spring声明式事务。以下是一个DAO示例:
public class UserDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
//添加用户
public int addUser(User user) {
String sql = "INSERT INTO user(username,password,age) VALUES (?,?,?)";
return this.jdbcTemplate.update(sql, new Object[] { user.getUsername(), user.getPassword(), user.getAge() });
}
}
在上面的代码中,我们在UserDAO
类中使用Spring提供的JdbcTemplate
类与数据源进行交互,并使用其中提供的update
方法提交SQL语句。
配置Spring声明式事务
现在,我们已经配置好了事务管理器、数据源和DAO。下面,我们来配置Spring声明式事务。事务配置方式如下:
<!--声明式事务配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!--事务设置-->
<aop:config>
<aop:pointcut id="allMethod" expression="execution(* com.example.*.*DAO.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allMethod" />
</aop:config>
其中,aop:config
标签用来定义切入点和通知类型,这里的pointcut
表示对所有DAO类中的全部方法进行拦截,通知类型为传播方式为REQUIRED的声明式事务管理。在这里,我们定义了四种类型的拦截方式:
-
对add、update、delete*三类方法进行事务管理,传播方式为REQUIRED。
-
对所有方法进行事务管理,传播方式为REQUIRED,同时设置readOnly为true,表示只读性质事务。
声明式事务使用示例
在上面的配置完成后,我们可以进行事务间的开启、提交和回滚操作,以下是几个使用示例。
1. 添加用户(事务成功)
//创建用户DAO
UserDAO userDAO = new UserDAO();
userDAO.setDataSource(dataSource);
//新建事务
DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(transDefinition);
try {
//业务操作
User newUser = new User();
newUser.setUsername("testuser");
newUser.setPassword("testpassword");
newUser.setAge(18);
int result = userDAO.addUser(newUser);
System.out.println("添加用户:" + result);
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
//回滚事务
transactionManager.rollback(status);
e.printStackTrace();
}
在上面的示例中,我们使用transactionManager
开启一个事务,并定义一个TransactionStatus
对象status
,用于管理事务的状态。此后,我们使用DAO类添加一个新用户,当添加完成后,使用事务管理器对该事务进行提交。
2. 添加用户(事务失败)
//创建用户DAO
UserDAO userDAO = new UserDAO();
userDAO.setDataSource(dataSource);
//新建事务
DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(transDefinition);
try {
//业务操作
User newUser = new User();
newUser.setUsername("testuser");
newUser.setPassword("testpassword");
newUser.setAge(200); //年龄不合法,导致事务失败
int result = userDAO.addUser(newUser);
System.out.println("添加用户:" + result);
//提交事务
transactionManager.commit(status);
} catch (Exception e) {
//回滚事务
transactionManager.rollback(status);
e.printStackTrace();
}
在上面的示例中,我们使用transactionManager
开启一个事务,并定义一个TransactionStatus
对象status
,用于管理事务的状态。此后,我们使用DAO类添加一个新用户,当添加完成后,使用事务管理器对该事务进行提交。由于该用户年龄属性不合法,此时事务将失败,会回滚数据。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring声明式事务配置使用详解 - Python技术站