Hibernate:继承策略,以及持久化抽象集合双向时的注释

时间:2017-02-01 10:45:38

标签: java hibernate inheritance associations

在尝试使用Hibernate双向持久化抽象集合时,我正在努力使用继承策略和关联注释的正确组合。 到目前为止,我所做的所有尝试都失败了,大多数人抱怨@ManyToOne引用了一个未知的身份。

鉴于以下示例,我的问题是

  • 维护hibernate继承策略的最佳方法是什么 在结构下面?

  • 哪个行ID生成符合继承策略?

  • 如何注释每个类(例如@Entity,@ MappedSuperclass)?
  • 如何注释方法或字段定义(例如@ManyToOne,@ OneToMany?

由于我的代码嵌入在一个更大的结构中,每个类都相当大,这里有一个关于汽车的模拟 - 这仍然很大。有些关系,如果我真的会模拟汽车,我会以不同的方式建模,但这个模拟希望以更可消化的形式描述基本问题,而不是我真实代码中的所有压载物。

关系看起来像这样:

<UML class diagram>

相关的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
    }
}

我会很乐意提供任何帮助。也欢迎解释解决方案的网页链接,因为我无法完全找到解决这个问题的网页。

1 个答案:

答案 0 :(得分:0)

  

为以下结构维护hibernate继承策略的最佳方法是什么?

这取决于模型的其余部分。最容易使用的策略是单表,但如果子类差异太大,则连接表策略或每类表策略可能会更好。只需阅读这些并选择一个你感到满意的人。但请注意,很难在层次结构中进一步改变继承策略 - 如果它可能的话(可能取决于JPA提供者)。

  

哪一行id生成符合继承策略?

我说那些是独立的,因为Hibernate应该为你处理。只需选择适合您需求的ID生成策略。你可能需要的是一个鉴别器列,让Hibernate识别每一行所代表的实体类。

  

如何注释每个类(例如@Entity,@ MappedSuperclass)?

这取决于您的需求,但我认为CarEngine不相关,所以他们是实体,而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
}