Hibernate:使用1:n关系和backref更新现有实体

时间:2014-10-22 06:37:03

标签: java hibernate postgresql

首先:我对hibernate的理解不是很深刻。我的大部分代码都是反复试验的。我正在使用带有注释的Hibernate 4.2.6和hibernate.cfg.xml,它下面是Postgres数据库。 我无法在这个问题上找到解决方案:

我有一个抽象的超类:

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
@MappedSuperclass
public abstract class AbstractEntity {
    @Id
    @GeneratedValue
    private Long id;

    //getter and setter
}

然后有:

import java.util.ArrayList;
import java.utils.List;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;

@Entity
public class Barn extends AbstractEntity {
    //...
    @OneToMany(mappedBy = "barn", fetch = FetchType.EAGER)
    private List<Horse> horses = new ArrayList<>();
    //other stuff and getters and setters

    public void addHorseToBarn(Horse horse) {
        horse.setBarn(this);
        this.horses.add(horse);
    }
}

最后是班级:

import java.util.ArrayList;
import java.utils.List;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class Horse extends AbstractEntity { 
    //...
    @ManyToOne
    @JoinColumn(name = "barn_id")
    private Barn barn;
    // other stuff and getters and setters
}

Hibernate为马创建一个表(使用barn的外键),barn然后使用其中的id为barn_horse创建。 我已经创建了一个谷仓,坚持了它,还有一匹坚持不懈的马。 现在我想用以下代码在其中两个之间创建关系:

public void takeHorseIntoBarn(Barn barn, Horse horse) {
    Session session = sessionFactory.openSession();
    try {
        session.beginTransaction();
        Barn b = (Barn) session.load(Barn.class, barn.getId());
        Horse h = (Horse) session.load(Horse.class, horse.getId());
        b.addHorseToBarn(h);
        session.update(h);
        session.update(b);
        session.getTransaction().commit();
    } catch(Exception e) {
        session.getTransaction().rollback();
    } finally {
        session.close();
    }
}

在控制台中,我只看到用于更新Horse的输出。当我之后查看我的数据库时,barn_horse中没有条目。在桌上马,谷仓的关键不在那里。 我已经尝试了几种方法,如果我没有阅读并尝试很多东西,我就不会在这里问。那么请你知道问题是什么吗?谢谢!

更新: 到目前为止我发现的:如果我删除mappedBy并向Barn添加一个Cascade.ALL我将在barn_horses表中获得所需的条目,但在实体Horse中我不会获得插入谷仓的ID。从谷仓我能够得到它的马匹。但是因为我使用马的谷仓作为背景,我想我需要&#39; mappedBy&#39;,因为我希望谷仓可以通过马访问而没有映射但是没有插入谷仓的ID进入马。所以这不是我正在寻找的解决方案......

2 个答案:

答案 0 :(得分:0)

首先,你在ManyToOne部分缺少referenceColumn? 我认为cascade就是你想要的。

答案 1 :(得分:0)

我终于明白了!我就这样做了:

在谷仓课上:

@OneToMany(mappedBy = "barn", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Horse> horses = new ArrayList<>();

public void addHorse(Horse horse) {
    this.horses.add(horse);
    horse.setBarn(this);
}

在马课上:

@ManyToOne
@JoinColumn(name = "barn_id")
private Barn barn;

更新关系:

Session session = sessionFactory.openSession();
try {
    session.beginTransaction();
    Barn b = (Barn) session.load(Barn.class, barn.getId());
    Horse h = (Horse) session.load(Horse.class, horse.getId());
    b.addHorse(h);
    session.update(b);
    session.update(h);
    session.getTransaction().commit();
} catch(Exception e) {
    session.getTransaction().rollback();
} finally {
    session.close();
}