我有一个非常满意的现有数据模型:

public class Garden {
    private String name; // "Oak Grove"
    private List<Plant> plants;
}

public class Plant {
    private String name; // "Cherry Tomato"
}


我想在Hibernate中使用以下条件对此进行映射:


Java中的Plant类不维护对其父级Garden的引用。这使Java层IMO的工作更加困难。
PLANT表应具有GARDEN_ID列,该列是GARDEN(ID)列的外键。


我在@OneToMany添加之前的初始设置:

@Entity(name = "GARDEN")
public class Garden {
    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "NAME", nullable = false)
    private String name; // "Oak Grove"

    // Not yet mapped
    private List<Plant> plants;
}

@Entity(name = "PLANT")
public class Plant {
    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "NAME", nullable = false)
    private String name; // "Cherry Tomato"
}


如何在@OneToMany上定义List<Plant> plants;批注,以使外键引用保留在Plant中?

如果我只添加:

@OneToMany(cascade = { CascadeType.ALL })
@JoinColumn(name = "GARDEN_ID")
private List<Plant> plants;


然后用植物保存花园失败,如下所示:

Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "GARDEN_ID"; SQL statement:
insert into PLANT (NAME, ID) values (?, ?) [23502-191]


因此看来,Hibernate并没有试图保留外键。有没有办法完全不破坏我的对象模型的方法?

编辑:我正在测试的方式是:

Garden garden = new Garden("Oak Grove");
garden.addPlant(new Plant("Cherry Tomato"));
gardenManager.save(garden);


在其中save()方法看起来非常休眠:

public void save(T item) {
    try (Session session = factory.openSession()) {
        Transaction transaction = session.beginTransaction();
        try {
            session.saveOrUpdate(item);
            transaction.commit();
        } catch (Exception ex) {
            System.out.println("Error occurred saving item: " + ex.getMessage());
            ex.printStackTrace();
            transaction.rollback();
        }
    }
}

最佳答案

Yogesh Sakurikar接近了,但是双向@JoinColumn有点偏离。在下面,您将看到如何双向或单向加入

@Entity(name = "GARDEN")
public class Garden {
    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "NAME", nullable = false)
    private String name; // "Oak Grove"

    // use this if you don't want a bi-directional relationship
    // @OneToMany
    // @JoinColumn(name = "ID", referencedColumnName="GARDEN_ID")
    // private List<Plant> plants;

    // use this if you want it bi-directional
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "garden")
    private Set<Plant> plants;
}

@Entity(name = "PLANT")
public class Plant {
    @Id
    @Column(name = "ID", nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "NAME", nullable = false)
    private String name; // "Cherry Tomato"

    // use this if you don't want a bi-directional relationship
    // @Column(name="GARDEN_ID")
    // private long gardenId;

    // use this if you want a bi-directional relationship
    @ManyToOne
    @JoinColumn(name = "GARDEN_ID", referencedColumnName="ID", nullable = false)
    private Garden garden;

}


下面的代码假定双向关系。否则,在完全描述任何孩子Garden.id之前,您需要了解您的Plant

Garden garden = new Garden("Oak Grove");
Plant plant = new Plant("Cherry Tomato")
plant.setGarden(garden); //don't forget to set the parent on the child
garden.addPlant(plant);
gardenManager.save(garden);

10-04 13:13