接着昨天的jdbcTemplate,笔者今日单独配置了service层的事物管理,把遇到的问题和所得贴出来和大家分享
先推荐一篇博客,讲述基于tx/aop的事物声明http://www.cnblogs.com/rushoooooo/archive/2011/08/28/2155960.html,LZ很强大
一:查阅资料,得知在使用XML配置声明式事物时,可以使用原始的TransactionProxyFactoryBean的方法或者是基于tx/aop命名空间的配置,由于后者较易理解,笔者决定使用后者进行配置:
<servlet-name>-servlet.xml
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.ibm.db2.jcc.DB2Driver"/>
<property name="url" value="jdbc:db2://192.168.11.11:60028/SSTDB"/>
<property name="username" value=11"/>
<property name="password" value="11"/>
</bean>
<!-- jdbcTemplate配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 事务管理器 -->
<bean name="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务传播特性 -->
<tx:advice id="TestAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置参与事务的类 -->
<aop:config>
<aop:pointcut id="allTestServiceMethod" expression="execution(* com.suning.sample.biz.*.*(..))"/>
<aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />
</aop:config>
<!-- 事务管理器 -->
<bean name="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
首先要建立事务管理器,和dataSource建立联系,对不同的多个事物进行统一的管理
<!-- 配置事务传播特性 -->
<tx:advice id="TestAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置参与事务的类 -->
<aop:config>
<aop:pointcut id="allTestServiceMethod" expression="execution(* com.suning.sample.biz.*.*(..))"/>
<aop:advisor pointcut-ref="allTestServiceMethod" advice-ref="TestAdvice" />
</aop:config>
(1):add*表示事物绑定的service类中以add开头的方法,REQUIRED表示若不存在事物就创建一个,即对应TranscationServiceImp中的addMoney表示是一个独立的事物
(2):execution中第一个*表示返回结果,第二个*表示所有类,第三个*表示类的方法,(..)表示方法的参数
(3):aop:advisor把类和类的事物配置结合到了一起
二:这个是使用事物的service类
TranscationServiceImp.java
package com.suning.sample.biz;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
public class TranscationServiceImp implements TranscationService{
private static final Logger logger = Logger.getLogger(TranscationServiceImp.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addMoney(int money) {
logger.debug("Mary账户加100,Jack账户减100");
String del_Sql = "UPDATE ORG_TEST SET MGRID = MGRID - ? WHERE EMPNAME = ?";
String add_Sql = "UPDATE ORG_TEST SET MGRID = MGRID + ? WHERE EMPNAME = ?";
jdbcTemplate.update(del_Sql,money,"Jack");
jdbcTemplate.update(add_Sql,money,"Mary");
}
}
情景假设如下:有两个人分别叫Mary和Jack,分别有200,300元如下,现在让Mary账户加100,Jack账户减少100,总账户还是500
设立事物的意义就是保证Mary加100和Jack减少100都同时满足的时候,sql才会提交,以避免Mary加100成功而Jack减100失败总账户是400的这种类似情况出现
程序运行结果:
三:在使用jdbcTemplate的时候报了空指针异常,当时我是这么写的代码
private JdbcTemplate jdbcTemplate;
我以为我配置了jdbcTemplate就行了,还是基础不扎实没有理解Spring的思想
正确的写法:
@Autowired
private JdbcTemplate jdbcTemplate;
只有当注解jdbcTemplate时,Spring才会在容器中通过如下
<!-- jdbcTemplate配置 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
去查找这个类,还有就是通过Ioc注释反转的Bean不能在使用的时候用new 创建,要不Spring将不会注入,Spring思想啊思想啊,加大看书力度
四:关于引入.xml配置文件和.properties的写法:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:conf/spring/sample-service.xml,
</param-value>
</context-param>
可以在web.xml文件中通过这样引入sample-service配置文件
<context:property-placeholder location="classpath:conf/freemarker.properties"
ignore-unresolvable="true" />
引入properties文件
五:新建sample-service.xml文件时候若是遇到如下问题:
Document root element "beans", must match DOCTYPE root "null".
推荐一篇博客