## 環境
Spring4 + hibernate5 + jpa
坑一
描述
打算使用es, 是以給hibernate 配置了攔截器, 如下
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.ejb.interceptor.session_scoped">
<value>per.posse.tool.interceptor.HibernateSessionInterceptor</value>
</entry>
</map>
</property>
</bean>
HibernateSessionInterceptor 實作了 org.hibernate.Interceptor 接口
問題
RETRIEVE, CREATE, CREATE, 全無問題, 但是UPDATE 操作毫無反應, 資料不更新, 也不報錯, 也不列印update的sql.
原因及解決
HibernateSessionInterceptor 具體實作還沒寫, 編譯器預設生成Interceptor接口的實作方法, 有個方法叫findDirty(), 編譯器預設實作空方法是
@Override
public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
String[] propertyNames, Type[] types) {
return new int[];
}
檢視描述
Called from flush(). The return value determines whether the entity is updated
- an array of property indices - the entity is dirty
- an empty array - the entity is not dirtinte
也就是hibernate 在執行 flush() 操作的時候, 會調用這個方法, 傳回值決定實體是否被update傳回值有值, 實體被改寫, 需要更新持久化上下文, 傳回值是空數組, hibernate不認為實體被改動, 不執行更新操作,傳回null, 則由hibernate 預設的dirty-checking 機制判斷是否需要更新, 它有自己的一套DirtyCheckEventListener, DirtyCheckEvent機制.
是以編譯器給我預設傳回new int[0], hibernate 認為實體不需要更新, 是以就沒有執行update, 是以把傳回先改成null ,再做update操作, 列印sql, 資料庫更新.
OK.