Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
350 views
in Technique[技术] by (71.8m points)

java - Hibernate interceptor and event listeners

I wonder if it's possible to find out what hibernate really did to the database (i.e., committed changes). I'd like to notify another process on certain changes.

I guess that the EventTypes POST_COMMIT_DELETE, POST_COMMIT_UPDATE and POST_COMMIT_INSERT should do, but given exactly zero documentation, it's only a guess. Can someone confirm? Am I missing any?

I'm also unsure about how to obtain what gets really written. The PostInsertEvent contains both Object entity and Object[] state, which of the two should I trust?


A side question: I'm using no XML, no Spring, no JPA, just Configuration and buildSessionFactory. Is this really the way listeners should be registered?

 EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory)
    .getServiceRegistry()
    .getService(EventListenerRegistry.class);
registry.appendListeners(....);

I'm asking as its 1. dependent on an implementation detail, 2 totally ugly, 3. nearly perfectly undiscoverable.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, it is possible to notify another process(For Example: Auditing) after committing certain changes in the DB. That is to do certain things right after the JDBC transaction(Hibernate wraps JDBC transaction ) is committed using Custom Interceptors and Events of Hibernate.

You can create your own custom interceptor class by extending it by EmptyInterceptor class of hibernate. And by overriding the below afterTransactionCompletion(Transaction tx) method of EmptyInterceptor to do certain tasks after the transaction has been committed.

public class AuditLogInterceptor extends EmptyInterceptor {
 @Override
 public void afterTransactionCompletion(Transaction tx) {
    System.out.println("Task to do after transaction ");
 }
}

The Event system can be used in addition, or as a replacement, for interceptors.

Below listed are few ways to perform certain task after transaction event is completed/committed

1.Implement AfterTransactionCompletionProcess interface from org.hibernate.action package and implement the below method. documentation

void doAfterTransactionCompletion(boolean success, SessionImplementor session) {
      //Perform whatever processing is encapsulated here after completion of the transaction.
}      

Otherwise, you can extend your CustomDeleteAction class with EntityDeleteAction and override the above doAfterTransactionCompletion method. documentation

2.By Implementing PostDeleteEventListener and using EventType.POST_COMMIT_DELETEfor post delete.
By Implementing PostInsertEventListener and using EventType.POST_COMMIT_INSERTfor post insert.
By Implementing PostUpdateEventListener and using EventType.POST_COMMIT_UPDATEfor post update.
Here are few examples of PostDeleteEventListener , PostUpdateEventListener and PostInsertEventListener.


The Object entity of PostInsertEvent gives the entity involved in the database operation.

The Object[] state of PostInsertEvent returns the session event source for this event. This is the underlying session from which this event was generated.
Below link contains the documentation for PostInsertEvent Members.

http://mausch.github.io/nhibernate-3.2.0GA/html/6deb23c7-79ef-9599-6cfd-6f45572f6894.htm


Registering event listeners: Below MyIntegrator class shows 3 ways to register event listeners.

public class MyIntegrator implements org.hibernate.integrator.spi.Integrator {

public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    // As you might expect, an EventListenerRegistry is the thing with which event listeners are registered  
    // It is a service so we look it up using the service registry
    final EventListenerRegistry eventListenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );

    // If you wish to have custom determination and handling of "duplicate" listeners, you would have to add an
    // implementation of the org.hibernate.event.service.spi.DuplicationStrategy contract like this
    eventListenerRegistry.addDuplicationStrategy( myDuplicationStrategy );

    // EventListenerRegistry defines 3 ways to register listeners:
    //     1) This form overrides any existing registrations with
    eventListenerRegistry.setListeners( EventType.AUTO_FLUSH, myCompleteSetOfListeners );
    //     2) This form adds the specified listener(s) to the beginning of the listener chain
    eventListenerRegistry.prependListeners( EventType.AUTO_FLUSH, myListenersToBeCalledFirst );
    //     3) This form adds the specified listener(s) to the end of the listener chain
    eventListenerRegistry.appendListeners( EventType.AUTO_FLUSH, myListenersToBeCalledLast );
}
}

Hence, Listeners registration to a event is dependent on implementation detail.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...