PersistentObjectException:传递给persist的分离实体

时间:2011-10-05 23:10:13

标签: java hibernate jpa playframework

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

从连接到websocket的启动Job调用多个作业。我正在使用的库为每个传入消息创建一个不同的线程。然后我在保存到数据库之前将线程转换为作业。我这样做,因为如果我允许原始线程调用save,则会抛出另一个关于将id从1更改为2或类似内容的PersistentObjectException。

我还有另一个正在运行的作业,它同时访问数据库。可能有什么不对?

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

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

2 个答案:

答案 0 :(得分:5)

基本上,这意味着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只能使用{{1 }}字段作为检测机制...

答案 1 :(得分:0)

我发现这个解决方法现在可以使用了。也许这与Gson和Jpa如何互动有关。不确定......

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