【问题标题】:How do I map relationships between entities of the same super class using JPA?如何使用 JPA 映射同一超类的实体之间的关系?
【发布时间】:2014-09-02 03:12:10
【问题描述】:

我需要使用 JPA/Hibernate 在两个实体之间建立关系:ChildFather,它们都扩展了实体 User。一个父亲可以没有孩子,每个孩子都必须有一个父亲。我可以毫无问题地插入一个父亲,但不能添加一个属于我之前插入的父亲的孩子。这是我添加孩子的方法:

    SelectStatement ss = new SelectStatement();
    ss.manager.clear();
    Father father =  ss.getFather(socialId);

    Child child = new Child();
    //Set some parameters
    dependente.setFather(father);

    titular.addChild(child);
    ss.manager.refresh(titular);
    ss.manager.persist(dependente);
    ss.manager.getTransaction().begin();
    try{
        ss.manager.getTransaction().commit();
        ss.close();
        return true;
    }
    catch(RollbackException e){
        ss.close();
        return false;
    }

班级用户:

   @Entity
   @Inheritance ( strategy = InheritanceType.JOINED )
   public class User{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int pk_user;

    @Column
    private String name;        
}

班主任:

@Entity
public class Father extends User{


    @OneToMany(mappedBy="father")
    @LazyCollection(LazyCollectionOption.FALSE)
    private Collection <Child> childs;

    @Column(nullable=true, unique=true)
    private String social_id;


    public void addChild(Child child){
        this.childs.add(child);
    }       
}

类子:

@Entity
public class Child extends User{

    //Here is the problem!
    @ManyToOne(optional = false)
    @JoinColumn(name = "pk_user")
    private Father father;

}

PS:为了清楚起见,我已经删除/更改了一些属性,所以不要担心不存在的 get/set 方法等。

以下代码产生错误“应使用可插入 = 假,可更新 = 假”。如果我确实使用,我会收到错误“无法添加或更新子行”。

我可以删除 User 类并将其所有属性复制到父亲和孩子,为这个问题创建一个解决方案。但是我真正的父/子/用户类足够复杂,可以避免这样做。

谢谢。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    我有类似的代码,它对我来说很好用(我在 JTA 环境中):

    create Father;
    em.persist(fatherInstance);
    em.flush(); //(with this I become assured, that the father is present in database )
    create child;
    em.persist(childInstance);
    em.flush();
    

    您真的需要延迟加载您孩子的名义字段的能力吗?如果需要,我想最好使用@JoinColumn(nullable=false)

    但为了更好地理解问题 - 最好查看确切的代码。

    【讨论】:

    • 谢谢伊利亚。我发现了问题并作为答案发布。我尝试了您的代码,最初flush() 启动了 TransactionRequiredException。但是如果flush()getTransaction().begin(); 之后,那么一切正常。但是,我仍然不知道为什么我必须使用flush()。每个事务持久化一个对象就可以了。
    • 关于延迟加载,代码实际上做的不是延迟加载,只是为了方便。每次我加载一个父亲对象时,我都会使用他所有的孩子对象,而且我知道一次不会有很多孩子和用户一个父亲对象,所以我认为这不会有问题。为什么使用@JoinColumn(nullable=false) 比使用@LazyCollection(LazyCollectionOption.FALSE) 更好?
    【解决方案2】:

    我发现了问题。我对 2 列使用相同的列名。现在在 Child 表中,对于每个孩子,我都有一个指向超类的 pk_user 和指向孩子父亲的“pk_father”。

    @Entity
    public class Child extends User{
    
        //name has to be != then pk_user
        @ManyToOne(optional = false)
        @JoinColumn(name = "pk_father")
        private Father father;
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-10
      相关资源
      最近更新 更多