PersistentObjectException

PersistentObjectException

在我的应用中,我已连接到网络套接字。
套接字正在发送JSON数据。随着它变得可用,我将其处理在另一个作业中。在每个作业中,我都使用GSON将JSON转换为模型对象。有3种模型,所有模型都是独立的,并且在MappedSuperclass中具有一个公共时间戳字段。他们没有ID显式字段。我在模型上调用save,并且在1000次中有1次抛出“PersistentObjectException:传递给持久对象的分离实体”。

从连接到网络套接字的启动作业中调用多个作业。我正在使用的库为每个传入消息创建一个不同的线程。然后,我将线程转换为作业,然后再保存到数据库。我这样做是因为,否则如果我允许原始线程调用save,则会引发另一个PersistentObjectException,将id从1更改为2或类似的东西。

我还有另一个正在运行的作业,它可以同时访问数据库。有什么事吗

@Override
public void onMessage(final WebSocketMessage message){
        new Job() {
            @Override
            public void doJob() {
                processMessage(message.getText());
            }
        }.now();

}

 public void processMessage(String message) {
        Appointment appointment = new Gson().fromJson(message, Appointment.class);
        appointment.save();
 }

 @Entity
 public class Appointment extends CalendarEvent {
       private String owner;
 }

 @MappedSuperclass
 public abstract class CalendarEvent extends Model {
       private long timestamp;
 }

编辑:添加了一些代码示例

最佳答案

基本上,这意味着EntityManager将不再跟踪它们:This is a good overview在您没有明确要求的情况下,如何将视为独立的,这很奇怪。但是解决方法可能是在您的DAO方法中使用“防御性”方法,并用merge这些奇怪的情况。即:

public void save (Model possiblyDetachedModel) {

   if (entityManager.contains(possiblyDetachedModel)) {
        entityManager.merge(possiblyDetachedModel);
    } else {
        entityManager.persist(possiblyDetachedModel);
    }
}

我并不特别喜欢它,因为当您用persist编码新对象时,不需要这样做。可能需要登录(或尽可能调试)“merge”分支并真正检查那些恶意对象-我很确定EntityManager只能将@Id字段用作检测机制...

09-28 04:25