Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在“中插入值”;“另一边”;JPA中的1对n关系(使用EclipseLink)_Java_Jpa_Jpa 2.0_Eclipselink_Glassfish 3 - Fatal编程技术网

Java 在“中插入值”;“另一边”;JPA中的1对n关系(使用EclipseLink)

Java 在“中插入值”;“另一边”;JPA中的1对n关系(使用EclipseLink),java,jpa,jpa-2.0,eclipselink,glassfish-3,Java,Jpa,Jpa 2.0,Eclipselink,Glassfish 3,我有一个应用程序使用JSF2、JPA2和EJB3.1在GlassfishV3上运行(因此它使用EclipseLink 2)。此应用程序有两个JPA实体,Person和Message,每个Message都有两个Person的引用,即消息发送方和消息接收方。Person类具有属性,提供对已发送或已接收的消息的访问。消息类是这样的: @Entity public class Message { @ManyToOne @JoinColumn(name="sender") priv

我有一个应用程序使用JSF2、JPA2和EJB3.1在GlassfishV3上运行(因此它使用EclipseLink 2)。此应用程序有两个JPA实体,
Person
Message
,每个
Message
都有两个
Person
的引用,即消息发送方和消息接收方。
Person
类具有属性,提供对已发送或已接收的
消息的访问。
消息
类是这样的:

@Entity
public class Message {
    @ManyToOne
    @JoinColumn(name="sender")
    private Person sender;

    @ManyToOne
    @JoinColumn(name="receiver")
    private Person receiver;
    // ... some stuff ...
}
Person
类如下所示:

@Entity
public class Person {
    @OneToMany(fetch=FetchType.EAGER, mappedBy="sender")
    private List<Message> sentMessages;

    @OneToMany(fetch=FetchType.EAGER, mappedBy="receiver")
    private List<Message> receivedMessages;
    // ... more stuff ...
}
然而,令人惊奇的事情发生了。当我注释掉标记为
[1]
[2]
的行并调用该方法时,当我在其他地方使用这些实体时,
发送方的发送消息和
接收方的接收消息列表中不会出现该消息,即使它们是从实体管理器中检索的(例如通过
EntityManager.find()
)。如果我取消注释它,那么消息将按预期出现在列表中

我觉得这很有趣,因为我设想了两种情况,当这些行被注释掉时:

  • 直接从数据库中检索
    发送方
    接收方
    实体,消息应该出现在它们的列表中,因为我保存了消息,因此关系将保留在数据库中;或
  • 发送方
    接收方
    实体从某些缓存中检索,因此它们已经将消息添加到列表中
显然,它不是这样工作的

我在Hibernate中找到了关于缓存的信息。基于此,我认为问题在于,由于缓存不是对象而是值,因此需要使用
EntityManager.merge()
方法“刷新”具有缓存值的实体

是这样吗?如果没有,这种行为的原因是什么?调用
EntityManager.merge()
是最好的解决方案吗


提前谢谢大家

我的理解是,当您持久化消息时,接收方和发送方实体不会自动保存到数据库中

我认为您应该正确设置级联选项。也许这篇文章会有所帮助


问题在于您违反了对象标识。您的person对象来自不同的事务,因此将分离不同的持久性单元和。通过从新消息中引用它们,您已经损坏了持久性单元,因为您现在知道如何从托管对象中引用分离的对象。i、 e.如果你为任何一个人做一个find(),你会得到另一个人

您应该首先在当前事务/持久性上下文中查找()每个人,然后与他们一起创建消息,或者在新消息上使用merge()而不是persist(),作为与分离对象的merge

创建后,消息对象不在人员的消息中的原因是,您使用的是共享缓存(EclipseLink的默认设置),并且如果没有合并,您从未将消息添加到受管人员对象(仅分离的对象)。因为manytone定义了数据库中的关系,所以可以禁用缓存,或者调用person上的refresh来获取正确的消息。但是,正确的解决方案是不要损坏对象模型

看,,

我认为不必保存发送者和接收者,因为关系是在
消息
端注册的。此外,我看不到任何级联(实际上可能是删除级联)的原因,因为
持久化
级联不起作用(
个人
s已经持久化),并且
合并
级联也不起作用。但是我可能会错过一些东西。。。(OTOH,非常感谢这篇文章,它真的很棒)。
@Stateless
public class MessageDAOImpl implements MessageDAO {
    public Message crete(Person sender, Person receiver) {
        Message message = new Message();
        message.setSender(sender);
        message.setReceiver(receiver);
        entityManager.persist(message);
        // Puting in other objects, hoping it will work
        sender.getSentMessages().add(message);
        receiver.getReceivedMessages().add(message);

        // Saving sender and receiver: here comes the interesting part
        entityManager.merge(sender);    // [1]
        entityManager.merge(receiver); // [2]
        return message;
    }
}