gpt4 book ai didi

java - 如何使用JPA生命周期事件获取实体数据

转载 作者:行者123 更新时间:2023-12-02 08:12:27 28 4
gpt4 key购买 nike

我有一个 RESTful API,它使用带有 @EntityListners 注释的实体类。在 EntityListner.java 中,我有一个用 @PostPersist 注释的方法。因此,当该事件触发时,我想提取有关刚刚保存到数据库的实体的所有信息。但是当我尝试这样做时,Glassfish 会生成异常,并且 EntityListner 类中的方法未按预期执行。这是代码

public class EntityListner {
private final static String QUEUE_NAME = "customer";
@PostUpdate
@PostPersist
public void notifyOther(Customer entity){
CustomerFacadeREST custFacade = new CustomerFacadeREST();
Integer customerId = entity.getCustomerId();
String custData = custFacade.find(customerId).toString();
String successMessage = "Entity added to server";
try{
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.queueDeclare(QUEUE_NAME, false, false, false, null);
// channel.basicPublish("", QUEUE_NAME, null, successMessage .getBytes());
channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());
channel.close();
connection.close();


}
catch(IOException ex){

}
finally{

}
}
}

如果我发送注释掉的 successMessage 消息而不是 custData,一切正常。

http://www.objectdb.com/java/jpa/persistence/event以下内容是关于实体生命周期方法的,我想知道这里是否是这种情况。

To avoid conflicts with the original database operation that fires the entity lifecycle event (which is still in progress) callback methods should not call EntityMan­ager or Query methods and should not access any other entity objects

有什么想法吗?

最佳答案

正如该段落所述,该标准不支持从实体监听器内部调用实体管理器方法。正如 Heiko Rupp 在他的回答中所说,我强烈建议从持久化实体构建 custData。如果这不可行,请考虑:

  • 异步通知。 我真的不推荐这样做,因为它可能取决于正常工作的时间:
public class EntityListener {    private final static String QUEUE_NAME = "customer";    private ScheduledExecutorService getExecutorService() {        // get asynchronous executor service from somewhere        // you will most likely need a ScheduledExecutorService        // instance, in order to schedule notification with        // some delay. Alternatively, you could try Thread.sleep(...)        // before notifying, but that is ugly.    }    private void doNotifyOtherInNewTransaction(Customer entity) {        // For all this to work correctly,        // you should execute your notification        // inside a new transaction. You might        // find it easier to do this declaratively        // by invoking some method demarcated        // with REQUIRES_NEW        try {            // (begin transaction)            doNotifyOther(entity);            // (commit transaction)        } catch (Exception ex) {            // (rollback transaction)        }    }    @PostUpdate    @PostPersist    public void notifyOther(final Customer entity) {        ScheduledExecutorService executor = getExecutorService();        // This is the "raw" version        // Most probably you will need to call        // executor.schedule and specify a delay,        // in order to give the old transaction some time        // to flush and commit        executor.execute(new Runnable() {            @Override            public void run() {                doNotifyOtherInNewTransaction(entity);            }        });    }    // This is exactly as your original code    public void doNotifyOther(Customer entity) {        CustomerFacadeREST custFacade = new CustomerFacadeREST();         Integer customerId = entity.getCustomerId();        String custData = custFacade.find(customerId).toString();        String successMessage = "Entity added to server";        try {            ConnectionFactory factory = new ConnectionFactory();            factory.setHost("localhost");            Connection connection = factory.newConnection();            Channel channel = connection.createChannel();            channel.queueDeclare(QUEUE_NAME, false, false, false, null);            channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());              channel.close();            connection.close();        }        catch(IOException ex){        }        finally {        }    }    } 
  • 注册一些提交后触发器(如果 Heilo Rupp 的答案不可行,我的建议)。这与时间无关,因为它保证在刷新到数据库后执行。此外,它还有一个额外的好处,即如果您最终回滚事务,您无需通知。执行此操作的方法取决于您用于事务管理的内容,但基本上您创建某个特定实例的实例,然后将其注册到某个注册表中。例如,对于 JTA,它将是:
public class EntityListener {    private final static String QUEUE_NAME = "customer";    private Transaction getTransaction() {        // get current JTA transaction reference from somewhere    }    private void doNotifyOtherInNewTransaction(Customer entity) {        // For all this to work correctly,        // you should execute your notification        // inside a new transaction. You might        // find it easier to do this declaratively        // by invoking some method demarcated        // with REQUIRES_NEW        try {            // (begin transaction)            doNotifyOther(entity);            // (commit transaction)         } catch (Exception ex) {            // (rollback transaction)         }    }    @PostUpdate    @PostPersist    public void notifyOther(final Customer entity) {        Transaction transaction = getTransaction();        transaction.registerSynchronization(new Synchronization() {            @Override            public void beforeCompletion() { }            @Override            public void afterCompletion(int status) {                if (status == Status.STATUS_COMMITTED) {                    doNotifyOtherInNewTransaction(entity);                }            }        });                 }    // This is exactly as your original code    public void doNotifyOther(Customer entity) {        CustomerFacadeREST custFacade = new CustomerFacadeREST();         Integer customerId = entity.getCustomerId();        String custData = custFacade.find(customerId).toString();        String successMessage = "Entity added to server";        try {            ConnectionFactory factory = new ConnectionFactory();            factory.setHost("localhost");            Connection connection = factory.newConnection();            Channel channel = connection.createChannel();            channel.queueDeclare(QUEUE_NAME, false, false, false, null);            channel.basicPublish("", QUEUE_NAME, null, custData.getBytes());              channel.close();            connection.close();        }        catch(IOException ex){        }        finally {        }    }    }

如果您使用 Spring 事务,代码将非常相似,只是进行一些类名更改。

一些提示:

关于java - 如何使用JPA生命周期事件获取实体数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13107363/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com