简体   繁体   中英

How do I execute named queries from a JPA EntityListener?

I have a requirement to set a date_updated value in my database for each row when that row is updated. Let's call the entity that I'm working with Order , which has a corresponding orders table in the database.

I've added the date_updated column to the orders table. So far, so good.

The @Entity Order object that I'm working with is provided by a third party. I do not have the ability to modify the source code to add a field called dateUpdated . I have no requirement to map this value to the object anyway - the value is going to be used for business intelligence purposes only and does not need to be represented in the Java entity object.

My problem is this: I want to update the date_updated column in the database to the current time each time an Order object (and its corresponding database table row) is modified.

Constraints:

  • We are using Oracle, Spring, JPA and Hibernate
  • I cannot use Oracle triggers to update the value. We are using a database replication technology that prevents us from using triggers.

My approach thus far has been to use a JPA EntityListener, defined in xml, similar to this:

<entity-mappings xmlns="....">
  <entity class="com.theirs.OrderImpl">
    <entity-listeners>
      <entity-listener class="com.mine.listener.OrderJPAListener" />
    </entity-listeners>
  </entity>
</entity-mappings>

My listener class looks like this:

public class OrderJPAListener { 

  @PostPersist
  @PostUpdate
  public void recordDateUpdated(Order order) {
    // do the update here
  }
}

The problem I'm having is injecting any sort of persistence support (or anything at all, really) into my listener. Because JPA loads the listener via its methods, I do not have access to any Spring beans in my listener class.

How do I go about injecting an EntityManager (or any Spring bean) into my listener class so that I can execute a named query to update the date_updated field?

How do I go about injecting an EntityManager (or any Spring bean) into my listener class so that I can execute a named query to update the date_updated field?

As noted above JPA 2.1 supports injecting managed beans to an Entity Listener via CDI. Whether or not Spring supports this I am not sure. The folloiwng post proposes a Spring specific solution.

https://guylabs.ch/2014/02/22/autowiring-pring-beans-in-hibernate-jpa-entity-listeners/

A possible alternative approach would be however to override the SQL generated by Hibernate on an update which is possible as detailed below.

https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/querysql.html#querysql-cud

This would be straightforward if you had the source as you would just need to add the @SQLUpdate annotation and tag on the additional date_update column. As you don't however you would need to look at redefining the metadata for that Entity via an xml configuration file and defining the sql-update statement as outlined above:

https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/xml-overriding.html#xml-overriding-principles-entity

Since JPA 2.1 Entity Listeners are CDI managed. Have you tried using @PersistenceUnit annotation? Are you using JTA transaction type?

Otherwise you could use Persistence.createEntityManagerFactory within the Listener class to retrieve the Persistence Context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM