在项目中遇到利用hibernate执行查询后居然对数据库记录进行了更新,导致了错误。
代码如下:
public List getRetailDCList(CreditOrderScope scope) {
List rst = rcDao.getRetailDCList(scope);
for (int n = 0; n < rst.size(); n++) {
RetailDC fp = (RetailDC) rst.get(n);
Hibernate.initialize(fp.getRetailDCPackage());
Hibernate.initialize(fp.getNsClient());
Hibernate.initialize(fp.getBpBank());
if (fp.getNsClient() != null) {
Hibernate.initialize(fp.getNsClient().getPayType());
}
}
return rst;
}
在return 之后调用了spring的jar包,事物拦截器拦截后执行到invock方式时,就对记录进行了update动作。
刚开始疑似事物的原因。因此对原来的事物稍作了修改。
原来applicationContext.xml中事物:(定义抽象事物,需要事物的类通过继承的方式使用事物)
<bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="bankInterfaceService" parent="baseTxProxy"> <property name="target"> <bean class="com.service.impl.BankInterfaceServiceImpl" parent="baseService"> </bean> </property> </bean>
继承事物后是对类中所有的 set get save read 方法都使用了同样的事物,为了单独设置事物的属性,对这些属性进行了继承修改。对get方法事物属性设置了readonly。修改后如下:
<bean id="bankInterfaceService" parent="baseTxProxy"> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="set*">PROPAGATION_REQUIRED</prop> <prop key="process*">PROPAGATION_REQUIRED</prop> <prop key="read*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> <property name="target"> <bean class="com.nstc.dnaf.service.impl.BankInterfaceServiceImpl" parent="baseService"> </bean> </property> </bean>
至此问题解决完毕。后来探究查询后进行了更新的真正原因。是因为在查询的实体类中有如下写法。
public String getFeedBack() { if(this.feedBack==null){ this.feedBack=""; } return this.feedBack; }
因为在数据库中是null,在hibernate查询时会设置成“”。hibernate会任务session中的实体发生了改变,就会执行update。至此原因
在进行脏数据检查时会认为它是脏数据,需要更新
另外一种解决方式:
采用的解决办法是将配置文件增加一个属性access="field" 这样就不会通过get方法比较属性而直接访问属性字段
<property name="feedBack" type="java.lang.String" access="field">
<column name="feedBack" length="50" />
</property>