2012-08-01 55 views
0

我正在使用Hibernate Envar進行審計。Hibernate Envers - org.hibernate.exception.ConstraintViolationException:無法執行JDBC批更新

這裏是我的代碼和配置

hibernate.cfg.xml文件配置

<!-- Audit --> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="post-insert"/> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="post-update"/> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="post-delete"/> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-update"/> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="pre-collection-remove"/> 
     <listener class="org.hibernate.envers.event.AuditEventListener" type="post-collection-recreate"/> 

單樣本實體Annoted與@Audited

@Entity 
@Table(name = "Users") 
@Audited 
public class User extends GenericDomain implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 
    @Column(length=100) 
    private String name; 
    @Column(length=60) 
    private String username; 
    @Column(length=130) 
    private String password; 
    // Getter and setter with more fields 
} 

我創建了一個RevistionEntity記錄審覈對於登錄用戶,我們對其進行日誌審計爲

@Entity 
@Table(name = "REVISIONS") 
@RevisionEntity(CustomRevisionListener.class) 
public class CustomRevisionEntity { 

    @Id 
    @GeneratedValue 
    @RevisionNumber 
    private int id; 
    @RevisionTimestamp 
    private long audit_timestamp; 
    private String username; 
    private Long userid; 
    // Getter and Setter 
} 

這裏是我的監聽器類

public class CustomRevisionListener implements RevisionListener { 

    public void newRevision(Object revisionEntity) { 
     CustomRevisionEntity revision = (CustomRevisionEntity) revisionEntity; 
     revision.setUsername("username"); //for testing 
    } 
} 

對於插入/刪除它工作正常。

但對於更新查詢它給下面的異常如

[ERROR] [http-8080-1 06:05:26] (JDBCExceptionReporter.java:logExceptions:101) Duplicate entry '1085-3' for key 1 
[ERROR] [http-8080-1 06:05:26] (AbstractFlushingEventListener.java:performExecutions:324) Could not synchronize database state with session 
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 
     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) 
     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) 
     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:179) 
     at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) 
     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) 
     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206) 
     at org.hibernate.envers.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:157) 
     at org.hibernate.envers.synchronization.AuditProcess.beforeCompletion(AuditProcess.java:164) 
     at org.hibernate.transaction.JDBCTransaction.notifyLocalSynchsBeforeTransactionCompletion(JDBCTransaction.java:274) 
     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:140) 
     at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) 
     at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) 
     at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy106.deleteSaleRecord(Unknown Source) 
     at org.commission.controller.salerecord.SaleRecordController.delete(SaleRecordController.java:753) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 
     at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176) 
     at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426) 
     at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414) 
     at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) 
     at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) 
     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) 
     at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) 
     at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.commission.util.SessionFilter.doFilter(SessionFilter.java:71) 
     at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
     at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
     at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) 
     at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
     at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286) 
     at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) 
     at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) 
     at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) 
     at java.lang.Thread.run(Thread.java:619) 
Caused by: java.sql.BatchUpdateException: Duplicate entry '1085-3' for key 1 
     at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2018) 
     at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449) 
     at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723) 
     at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) 
     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) 
     ... 46 more 

這裏是我的通用更新代碼的所有實體

public E update(E entity) { 
     getSession().update(entity); 
     return entity; 
    } 
+0

@Teinacher,請檢查我是否發佈了更新代碼。只有在審計的情況下才會發生這種情況。如果沒有審覈,我的CRUD功能正在完善。 – 2012-08-03 05:10:50

回答

1

遺憾的是不完整的堆棧跟蹤和表的SQL定義,很難說這裏發生了什麼。這些是我會檢查的事情:

  1. 審計表上的約束/ PK? - 是否有可能你的主鍵缺少修訂號和修訂類型 - 我發生過這種情況,因爲更新和刪除發生在同一個會話中某個實體(我認爲它與Cascade操作有關,但是我現在無法回憶),並且我預計實體表的修訂號+ PK足以唯一標識審計表中的每一行。

  2. 請記住,默認情況下,刪除的實體只包含原始實體的修訂號,修訂類型和ID/PK。如果您在審計表上有NOT NULL約束,那可能會導致失敗。您可以通過將org.hibernate.envers.store_data_at_delete屬性設置爲true來解決此問題。

+0

嘿,我有同樣的問題,你在那裏#1。我的審計表是一個帶有@ @ JoinTable和多個PK列的多對多表,在審計表中總共有4個。但是,升級到PK中的所有四列後,我仍然從休眠中得到錯誤。 'org.hibernate.NonUniqueObjectException:具有相同標識符值的不同對象已經與會話相關聯。你的#2對我來說也是「真的」。任何想法爲什麼Hibernate認爲它具有相同的身份? – Andreas 2014-05-07 14:15:34

+0

很久以前,現在可能會發佈一個新的問題與您的表的定義。我認爲最後我只是從審計表中刪除了密鑰,因爲這太難以維持。 – ifx 2014-05-15 08:36:43

+0

我最終重寫了視圖代碼,以避免這種情況發生,很多麻煩。 – Andreas 2014-05-20 11:41:24