2017-05-12 1 views
0

J'utilisais Hibernate 3, maintenant je migre vers Hibernate 5, et certains problèmes sont survenus (bien sûr)."impossible de réinitialiser le lecteur" tout en sauvegardant BLOB

J'ai plusieurs objets DAO qui sont stockés via Hibernate, et certains d'entre eux ont un paramètre/champ/colonne "modifié" qui est automatiquement mis à jour à l'heure actuelle à chaque sauvegarde/mise à jour dans Hibernate.

est simple 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;} 
} 

C'est intégrateur qui définit des modifications d'écoute:

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) { 
    } 
} 

C'est ModificationsEventListener qui met à jour en fait le paramètre "modifié":

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); 
} 

} 

Cette est le code qui sauve DAO:

 // 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; 
     } 

Mais ce code génère une erreur:

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 mise en veille prolongée est ce exécute:

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=? 

problème Apparemment que Hibernate insère enregistrement et juste après la mise à jour qui fait. FileInputStream ne l'aime pas parce qu'il est fermé juste après l'insertion.
Lorsque je désactive l'intégrateur (mise à jour du champ "modifié"), cela fonctionne correctement.

Y a-t-il un moyen de le faire fonctionner?

Répondre

0

Je viens de voir ceci:
How to autogenerate created or modified timestamp field?

Et cela m'a aidé à résoudre mon problème. J'ai dû utiliser EventType.PRE_UPDATE et EventType.PRE_INSERT dans l'intégrateur, au lieu de EventType.SAVE_UPDATE, EventType.SAVE et EventType.UPDATE. Et puis mettre à jour les valeurs dans ces auditeurs comme ceci: Où

setter état de propriété
Modifications doc=((Modifications)entity); 
doc.setModified(now); 
setPropertyState(state, propertyNames, "modified", now); 

est ici:

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; 
     } 
    } 
}