2017-05-12 4 views
0

Ich war mit Hibernate 3, jetzt bin ich auf Hibernate 5 migrieren, und einige Probleme aufgetreten (natürlich)."konnte Leser nicht zurücksetzen" beim Speichern von BLOB

Ich habe mehrere DAO-Objekte, die über Hibernate gespeichert werden, und einige von ihnen haben Parameter/Feld/Spalte "geändert", die bei jedem Speichern/Aktualisieren in Hibernate automatisch auf die aktuelle Zeit aktualisiert wird.

Dies ist einfach DAO:

@Entity 
@Table(name="attachments") 
@SequenceGenerator(name="common_attachments_seq", sequenceName="common_attachments_seq", allocationSize=1) 
public class AttachmentDAO implements Modifications { 
    private Long id; 
    private String name; 
    private Blob content; 
    private Date modified; 

    public AttachmentDAO() {} 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO, generator="common_attachments_seq") 
    @Column(updatable = false, nullable = false) 
    public Long getId() {return this.id;} 
    public void setId(Long id) {this.id=id;} 

    @Column 
    public String getName() {return this.name;} 
    public void setName(String name) {this.name=name;} 

    @Column 
    public Blob getContent() {return this.content;} 
    public void setContent(Blob content) {this.content=content;} 

    @Column 
    public Date getModified() {return modified;} 
    public void setModified(Date date) {modified=date;} 
} 

Dies ist Integrator, Modifikationen Zuhörers setzt:

public class HibernateIntegrator implements Integrator { 

    @Override 
    public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { 
     EventListenerRegistry eventListenerRegistry=serviceRegistry.getService(EventListenerRegistry.class); 

     ModificationsEventListener mod=new ModificationsEventListener(); 

     eventListenerRegistry.appendListeners(EventType.UPDATE, mod); 
     eventListenerRegistry.appendListeners(EventType.SAVE, mod); 
     eventListenerRegistry.appendListeners(EventType.SAVE_UPDATE, mod); 
    } 

    @Override 
    public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { 
    } 
} 

Dies ist ModificationsEventListener die "modifizierte" tatsächlich Updates Parameter:

public class ModificationsEventListener extends DefaultSaveOrUpdateEventListener { 

@Override 
public void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { 
    Object o=event.getObject(); 

    if (o instanceof Modifications) { 
     Date now=new Date(); 
     Modifications doc=((Modifications)o); 
     doc.setModified(now); 
    } 
    super.onSaveOrUpdate(event); 
} 

} 

Diese ist der Code, der DAO speichert:

 // DiskFileItem currentFile = file uploaded to server - Apache's commons-fileupload-1.3.2.jar 
     Session hibSession=null; 
     Transaction tx=null; 

     try { 
      SessionFactory sf=AttachmentsSessionFactory.getSessionFactory(); 

      hibSession=sf.openSession(); 
      tx=hibSession.beginTransaction(); 

      AttachmentDAO stub=new AttachmentDAO(); 
      stub.setName(fileName); 

      long length=currentFile.getSize(); 
      InputStream ins=currentFile.getInputStream(); // this is FileInputStream 
      LobCreator lobs=Hibernate.getLobCreator(hibSession); 
      Blob blob=lobs.createBlob(ins, length); 
      stub.setContent(blob); 

      hibSession.save(stub); 

      tx.commit(); 

      ins.close(); 
      currentFile.delete(); 

     } catch (Exception ex) { 
      if (tx!=null) tx.rollback(); 
      log.error("", ex); 
     } finally { 
      if (hibSession!=null&&hibSession.isOpen()) { 
       hibSession.close(); 
      } 
      hibSession=null; 
     } 

Aber dieser Code löst Fehler:

2017-05-12 11:20:38,253 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-127) could not reset reader 
2017-05-12 11:20:38,254 ERROR [org.hibernate.internal.SessionImpl] (default task-127) HHH000346: Error during managed flush [could not update: [com.test.persistence.AttachmentDAO#38]] 
2017-05-12 11:20:38,267 ERROR [com.gibon.qintegra.servlets.upload.AttachmentsUploadProgressListener] (default task-127) : org.hibernate.exception.GenericJDBCException: could not update: [com.gibon.qintegra.persistence.common.AttachmentDAO#38] 
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) 
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) 
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3111) 
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2961) 
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3341) 
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:145) 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582) 
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456) 
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) 
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) 
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282) 
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465) 
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963) 
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339) 
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485) 
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147) 
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) 
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) 
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65) 
at com.gibon.qintegra.servlets.upload.AttachmentsUploadProgressListener.currentFileFinished(AttachmentsUploadProgressListener.java:138) 
at com.gibon.qintegra.data4ajax.AttachmentsServant.doServe(AttachmentsServant.java:255) 
at com.gibon.qintegra.servlets.Data4Ajax.doProcess(Data4Ajax.java:74) 
at com.gibon.qintegra.servlets.Data4Ajax.doPost(Data4Ajax.java:24) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) 
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) 
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) 
at com.gibon.qintegra.filters.IECompatFilter.doFilter(IECompatFilter.java:44) 
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
at com.gibon.qintegra.filters.SecurityFilter.doFilter(SecurityFilter.java:89) 
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) 
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) 
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) 
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) 
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) 
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) 
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) 
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) 
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) 
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) 
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) 
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) 
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) 
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) 
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) 
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) 
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292) 
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81) 
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138) 
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135) 
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) 
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) 
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44) 
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272) 
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81) 
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104) 
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202) 
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
at java.lang.Thread.run(Thread.java:745) 
Caused by: java.sql.SQLException: could not reset reader 
at org.hibernate.engine.jdbc.BlobProxy.resetIfNeeded(BlobProxy.java:75) 
at org.hibernate.engine.jdbc.BlobProxy.getUnderlyingStream(BlobProxy.java:64) 
at org.hibernate.engine.jdbc.BlobProxy.getStream(BlobProxy.java:60) 
at org.hibernate.engine.jdbc.BlobProxy.invoke(BlobProxy.java:101) 
at com.sun.proxy.$Proxy118.getBinaryStream(Unknown Source) 
at org.postgresql.jdbc.PgPreparedStatement.setBlob(PgPreparedStatement.java:1154) 
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.setBlob(WrappedPreparedStatement.java:1157) 
at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$4$1.doBind(BlobTypeDescriptor.java:132) 
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:74) 
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:257) 
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:252) 
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:39) 
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2609) 
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3038) 
... 67 more 

SQL, die ausgeführt wird überwintern, ist dies:

Hibernate: 
select 
    nextval ('common_attachments_seq') 

Hibernate: 
insert 
into 
    sys_attachments 
    (content, modified, name, id) 
values 
    (?, ?, ?, ?) 

Hibernate: 
update 
    sys_attachments 
set 
    content=?, 
    modified=?, 
    name=?, 
where 
    id=? 

Anscheinend Problem ist, dass Hibernate Datensatz einfügt und direkt danach macht Update. FileInputStream mag es nicht, weil es direkt nach dem Einfügen geschlossen wird.
Wenn ich den Integrator deaktiviere (das "geänderte" Feld aktualisiere), funktioniert es OK.

Gibt es eine Möglichkeit, wie es funktioniert?

Antwort

0

Ich habe dies gerade gesehen:
How to autogenerate created or modified timestamp field?

Und es hat mir geholfen, mein Problem zu lösen. Ich musste EventType.PRE_UPDATE und EventType.PRE_INSERT in Integrator statt EventType.SAVE_UPDATE, EventType.SAVE und EventType.UPDATE verwenden. Und dann aktualisieren Werte in diesen Hörern wie folgt aus:

Modifications doc=((Modifications)entity); 
doc.setModified(now); 
setPropertyState(state, propertyNames, "modified", now); 

Wo Eigenschaft Zustand Setter hier:

private void setPropertyState(Object[] propertyStates, String[] propertyNames, String propertyName, Object propertyState) { 
    for(int i=0;i<propertyNames.length;i++) { 
     if (propertyName.equals(propertyNames[i])) { 
      propertyStates[i]=propertyState; 
      return; 
     } 
    } 
} 
Verwandte Themen