在尝试使用Hibernate双向持久化抽象集合时,我正在努力使用继承策略和关联注释的正确组合。 到目前为止,我所做的所有尝试都失败了,大多数人抱怨@ManyToOne引用了一个未知的身份。
鉴于以下示例,我的问题是
维护hibernate继承策略的最佳方法是什么 在结构下面?
哪个行ID生成符合继承策略?
由于我的代码嵌入在一个更大的结构中,每个类都相当大,这里有一个关于汽车的模拟 - 这仍然很大。有些关系,如果我真的会模拟汽车,我会以不同的方式建模,但这个模拟希望以更可消化的形式描述基本问题,而不是我真实代码中的所有压载物。
关系看起来像这样:
相关的java代码如下所示:
package persistence;
public abstract class MechanicalObject {
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public abstract void someMethod();
}
package persistence;
import java.util.List;
public abstract class Car extends MechanicalObject {
protected List<Engine> potentialEngines; // references to something that also extends MechanicalObject
protected List<Driver> potentialDrivers; // references to something that does not extend MechanicalObject
public List<Engine> getPotentialEngines() {
return potentialEngines;
}
public void setPotentialEngines(List<Engine> potentialEngines) {
this.potentialEngines = potentialEngines;
}
public List<Driver> getPotentialDrivers() {
return potentialDrivers;
}
public void setPotentialDrivers(List<Driver> potentialDrivers) {
this.potentialDrivers = potentialDrivers;
}
}
package persistence;
public abstract class Engine extends MechanicalObject {
private int driveRPM;
private Car parent; // bidirectional reference
public int getDriveRPM() {
return driveRPM;
}
public void setDriveRPM(int driveRPM) {
this.driveRPM = driveRPM;
}
public void someMethod() {
// do something
}
public abstract void anotherMethod();
}
package persistence;
public class Driver {
// db row id
private long id;
private String name;
private String licenceType;
private Car parent; // bidirectional reference
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLicenceType() {
return licenceType;
}
public void setLicenceType(String licenceType) {
this.licenceType = licenceType;
}
public Car getParent() {
return parent;
}
public void setParent(Car parent) {
this.parent = parent;
}
}
package persistence;
public class CombustionEngine extends Engine {
// db row id
private long id;
private int cylinderCapacity;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getCylinderCapacity() {
return cylinderCapacity;
}
public void setCylinderCapacity(int cylinderCapacity) {
this.cylinderCapacity = cylinderCapacity;
}
public void anotherMethod() {
// do something differently
}
}
package persistence;
public class ElectroEngine extends Engine {
// db row id
private long id;
private int nominalVoltage;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getNominalVoltage() {
return nominalVoltage;
}
public void setNominalVoltage(int nominalVoltage) {
this.nominalVoltage = nominalVoltage;
}
public void anotherMethod() {
// do something
}
}
package persistence;
public class TeslaModelX extends Car {
private long id;
private String licenceNumber;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLicenceNumber() {
return licenceNumber;
}
public void setLicenceNumber(String licenceNumber) {
this.licenceNumber = licenceNumber;
}
public void someMethod() {
// do something differently
}
}
package persistence;
public class VWBeetle extends Car {
private long id;
private String serialNumber;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public void someMethod() {
// do something differently
}
}
我会很乐意提供任何帮助。也欢迎解释解决方案的网页链接,因为我无法完全找到解决这个问题的网页。
答案 0 :(得分:0)
为以下结构维护hibernate继承策略的最佳方法是什么?
这取决于模型的其余部分。最容易使用的策略是单表,但如果子类差异太大,则连接表策略或每类表策略可能会更好。只需阅读这些并选择一个你感到满意的人。但请注意,很难在层次结构中进一步改变继承策略 - 如果它可能的话(可能取决于JPA提供者)。
哪一行id生成符合继承策略?
我说那些是独立的,因为Hibernate应该为你处理。只需选择适合您需求的ID生成策略。你可能需要的是一个鉴别器列,让Hibernate识别每一行所代表的实体类。
如何注释每个类(例如@Entity,@ MappedSuperclass)?
这取决于您的需求,但我认为Car
和Engine
不相关,所以他们是实体,而MechanicalObject
可能是映射的超类。当然,如果您希望其他实体引用任何MechanicalObject
,您可能必须将其作为实体,使用不同的映射方法或重新考虑您的需求/模型。
如何注释方法或字段定义(例如@ManyToOne,@ OneToMany?
根据需要进行操作并阅读注释。请记住,一方需要成为关系的所有者,即只有对该方的更改才会保留在数据库中。如果您不这样做,您可能会破坏您的模型并使JPA提供商感到困惑。在双向1-n关系上执行此操作的最简单方法是将mappedBy="..."
添加到1侧,即@OneToMany
。
例如,您的Car-Driver
关系可能如下所示:
class Car extends MechanicalObject {
@OneToMany( mappedBy="parent" )
protected List<Driver> potentialDrivers;
}
class Driver {
@ManyToOne
protected Car parent; //I'd use a better name here
}