EJB3 和手动层次结构持久性

Posted

技术标签:

【中文标题】EJB3 和手动层次结构持久性【英文标题】:EJB3 and manual hierarchy persistence 【发布时间】:2009-02-25 10:24:58 【问题描述】:

我有一个遗留数据库,我正在使用 EJB3 对其进行建模。数据库的状态很差,我们对如何插入数据库有一些不寻常的限制。现在我想在适合数据库结构的层次结构中对数据库进行建模,但我希望能够单独手动插入每个实体,而不需要持久性管理器尝试持久化实体子项。

我正在尝试类似以下的内容(样板被省略):

@Entity
@Table(name = "PARENT_TABLE")
public class Parent 
    @Id
    @Column(name = "ID")
    int id;

    @OneToMany
    List<Child> children;



@Entity
@Table(name = "CHILD_TABLE")
public class Child 
    @Id
    @Column(name = "ID")
    int id;   

现在这会引发异常:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST

现在我知道实体没有被标记为 PERSIST - 我不希望 EntityManager 保留它!我希望能够先坚持父母,然后是孩子——但不是在一起。想要这样做是有充分理由的,但它似乎不想玩。

【问题讨论】:

【参考方案1】:

欢迎来到 JPA 配置这个令人毛骨悚然的地方。

在您的情况下,您有两个选择:

    手动持久化新对象;或 自动持久化它。

要自动持久化它,您需要注释关系。这是一个常见的一对多习语:

@Entity
@Table(name = "PARENT_TABLE")
public class Parent 
  @Id private Long id;

  @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
  private Collection<Child> children;

  public void addChild(Child child) 
    if (children == null) 
      children = new ArrayList<Child>();
    
    child.setParent(parent);
    children.add(child);
  


@Entity
@Table(name = "CHILD_TABLE")
public class Child 
  @Id private Long id;

  @ManyToOne
  private Parent parent;

  public void setParent(Parnet parent) 
    this.parent = parent;
  


Parent parent = // build or load parent
Child child = // build child
parent.addChild(child);

由于级联持久化,这将起作用。

注意:您必须自己在 Java 级别管理关系,因此手动设置父级。这很重要。

没有它,您需要手动持久化对象。您需要一个 EntityManager 来执行此操作,在这种情况下,它很简单:

entityManager.persist(child);

此时它将正常工作(假设一切正常)。

对于纯粹的子实体,我倾向于使用注释方法。这更容易。

我将提到 JPA 的一个问题:

Parent parent = new Parent();
entityManager.persist(parent);
Child child = new Child();
parent.addChild(child);

现在我对此有点生疏,但我相信如果您这样做可能会遇到问题,因为在添加子项之前父项已被持久化。无论您做什么,都要小心并检查这种情况。

【讨论】:

那么如果我将级联属性设置为PERSIST,并使用实体管理器来持久化父级,那么EntityManager是否也会尝试持久化子级?如果是这样,这不是我想要的,因为我需要能够独立地坚持 Parent 和 Child。 顺便说一句,反向链接的省略是故意的——我只想对关系进行单向建模。这会导致问题,即是否需要双向关系? 父母对孩子的一种方式可能会有问题。有点生锈。从孩子到父母的一种方式更容易。 P->C 的问题是外键驻留在孩子中,因此需要映射。能详细说说你的情况吗? 顺便说一句,“坚持”并不完全意味着您在 JPA 中的想法。它只是使对象成为一个托管对象,如果事务被提交,则可以保存(但假设这一切都在事务中,则保存直到提交才会发生)。为什么要独立保存?好奇。 对于一种方式的父子关系,您需要一个 @JoinTable 用于它们之间的映射。

以上是关于EJB3 和手动层次结构持久性的主要内容,如果未能解决你的问题,请参考以下文章

从 JPA/EJB3 持久性上下文中分离实体

EJB3 + JEE6:啥是持久定时器?

HSQLDB EJB3.0 Hibernate 无法连接到数据库

JPA与EJB3的关系

我应该使用哪个 EJB 3 持久提供程序?

EJB3.0的一些学习