在 Hibernate 中使用 JPA 注释来描述外键仅在子 table 中的 @OneToMany 关系
Using JPA annotations with Hibernate to describe @OneToMany relationship where foreign key is only in child table
我有一个非常满意的现有数据模型:
public class Garden {
private String name; // "Oak Grove"
private List<Plant> plants;
}
public class Plant {
private String name; // "Cherry Tomato"
}
我想在具有以下条件的 Hibernate 中映射它:
Java 中的 Plant
class 不维护对其父 Garden
的引用。这使得 Java 层的事情变得更加困难,IMO。
PLANT
table 应该有一个 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"
}
如何在 List<Plant> plants;
上定义 @OneToMany
注释,以便在 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()
方法看起来很Hibernate-ey:
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();
}
}
}
对于一对多的关系,如果工厂要保持关系,你需要使用双向来定义它。
这是我认为你应该能够实现的:
@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"
@OneToMany(fetch = FetchType.LAZY, mappedBy = "garden")
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"
@ManyToOne
@JoinColumn(name = "GARDEN_ID", nullable = false)
Garden garden;
}
这种双向方法会让实体管理器知道两者之间存在关系,因为一方面是一对多,另一方面是多对一。希望这会有所帮助。
Yogesh Sakurikar 很接近,但 bi-directional @JoinColumn
有点偏离。下面您将看到如何双向加入或 mono-riectionally
@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;
}
下面的代码假定 bi-directional 关系。否则你需要先了解你的 Garden.id
才能完整描述任何 child 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);
我有一个非常满意的现有数据模型:
public class Garden {
private String name; // "Oak Grove"
private List<Plant> plants;
}
public class Plant {
private String name; // "Cherry Tomato"
}
我想在具有以下条件的 Hibernate 中映射它:
Java 中的
Plant
class 不维护对其父Garden
的引用。这使得 Java 层的事情变得更加困难,IMO。PLANT
table 应该有一个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"
}
如何在 List<Plant> plants;
上定义 @OneToMany
注释,以便在 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()
方法看起来很Hibernate-ey:
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();
}
}
}
对于一对多的关系,如果工厂要保持关系,你需要使用双向来定义它。 这是我认为你应该能够实现的:
@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"
@OneToMany(fetch = FetchType.LAZY, mappedBy = "garden")
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"
@ManyToOne
@JoinColumn(name = "GARDEN_ID", nullable = false)
Garden garden;
}
这种双向方法会让实体管理器知道两者之间存在关系,因为一方面是一对多,另一方面是多对一。希望这会有所帮助。
Yogesh Sakurikar 很接近,但 bi-directional @JoinColumn
有点偏离。下面您将看到如何双向加入或 mono-riectionally
@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;
}
下面的代码假定 bi-directional 关系。否则你需要先了解你的 Garden.id
才能完整描述任何 child 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);