<!-- AOP方式配置事务 ,定义事务建议-->
<tx:advice id="transactionAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="create*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="generate*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="edit*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="remove*" propagation="REQUIRED"/>
<tx:method name="repair" propagation="REQUIRED"/>
<tx:method name="deleteAndRepair" propagation="REQUIRED"/>
<!--hibernate4必须配置为开启事务 否则 getCurrentSession()获取不到 -->
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
<tx:method name="count*" propagation="REQUIRED" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" read-only="true"/>
<tx:method name="list*" propagation="REQUIRED" read-only="true"/>
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config expose-proxy="true">
<!-- 定义切入点 -->
<aop:pointcut id="transactionPointcut" expression="execution(* com.panasign..service..*.*(..))" />
<!-- 把建议引用到切入点中 -->
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"/>
</aop:config>
说明:
Spring + Hibernate
此处遇到的事务处理:
private BaseDaoInterface<BoProduct> dao;
@Override
public ProductDetailedVO getProductDetailedById(String boProductId) {
ProductDetailedVO vo = new ProductDetailedVO();
Map<String,Object> params = new HashMap<String, Object>();
params.put("boProductId", boProductId);
// get方法查询
BoProductDetailed bo = dao.get(hql, params);
// saveOrUpdate方法
dao.update(bo);
dao.flush();
vo=parseToVO(bo);
return vo;
}
此时后台报错:
Connection is read-only. Queries leading to data modification are not allowed
个人理解:
首先执行了,get查询方法。拿到的对象:
因为:
<tx:method name="get*" propagation="REQUIRED" read-only="true"/>
所以拿到对象,
第二次 访问数据库
再去执行update的时候,该对象仍是: read-only="true"
问题解决:
解决:在执行第一次事务的时候
getProductDetailedById(**) // 已经告诉 hibernate,是get查询方法 事务执行 ;
// 所以当再次 执行下面的操作时
dao.update(bo);
会报该异常,
那现在修改问题很简单了:
public ProductDetailedVO getProductDetailedById(String boProductId);
| 修改为 |
public ProductDetailedVO updateProductDetailedById(String boProductId);
<!-- Spring 只负责初始化dao与Service的注解,由spring管理service可以使事务配置生效 -->
<context:component-scan base-package="com.**.service"/>
<context:component-scan base-package="com.**.dao"/>
其实问题很简单
项目中配置了:
spring 自动扫描,dao/service 下面java文件,将带有@service @controller注解的类, 注册为Bean.
上面问题中get为最外面的方法并共享了对象,该对象是只读的。