简体   繁体   English

Hibernate中的双向一对一关系

[英]Bidirectional one-to-one relationships in Hibernate

There are two tables: Airplane and Engine 有两个表:飞机和引擎

The Engine table is made up as follows [Engine_ID, Engine_Name,Airplane_Owner_ID] . 引擎表由以下[Engine_ID, Engine_Name,Airplane_Owner_ID]
The Airplane table is made up as follows [Airplane_ID, Left_Engine, Right_Engine] “飞机”表的组成如下[Airplane_ID, Left_Engine, Right_Engine]

Left_Engine and Right_Engine are foreign keys from the Engine table, moreover Airplane_Owner_ID is the foreign key from the Airplane table. Left_Engine和Right_Engine是引擎表中的外键,此外Airplane_Owner_ID是飞机表中的外键。 Therefore there are three one-to-one relationships defined between the Airplane and Engine tables. 因此,飞机表和引擎表之间定义了三个一对一的关系。

I know how to specify single one-to-one relationships between two tables but how can I specify multiple relationships between two tables? 我知道如何指定两个表之间的单个一对一关系,但是如何指定两个表之间的多个关系? Is it the same process? 是同一过程吗?

How can these relationships be specified in Hibernate? 在Hibernate中如何指定这些关系?

"Left_Engine and Right_Engine are foreign keys from the Engine table, “ Left_Engine和Right_Engine是引擎表中的外键,
moreover Airplane_Owner_ID is the foreign key from the Airplane table." 而且Airplane_Owner_ID是Airplane表中的外键。”

Your problem is Airplane is referenced by Engine and Engine is referenced by Airplane . 您的问题是Engine引用了AirplaneAirplane引用了Engine In your data model each table is the child of the other. 在数据模型中,每个表都是另一个表的子级。 Cyclic dependencies are just as bad in the database as they are in other parts of the stack. 循环依赖关系在数据库中和在堆栈其他部分一样严重。

The best solution is to fix the data model. 最好的解决方案是修复数据模型。

  • Drop Left_Engine and Right_Engine from Airplane Airplane放下Left_EngineRight_Engine
  • add Engine_Position to Engine Engine_Position添加到Engine
  • add a unique constraint on Engine (Airplane_Owner_ID, Engine_Position) Engine (Airplane_Owner_ID, Engine_Position)上添加唯一约束Engine (Airplane_Owner_ID, Engine_Position)
  • also add a check constraint on Engine_Position for LEFT, RIGHT, or use a foreign key on a reference data table 还在Engine_Position为LEFT,RIGHT添加检查约束,或在参考数据表上使用外键

This model has two virtues: 该模型具有两个优点:

  1. Clear ownership - planes own engines, engines don't own planes. 明确的所有权-飞机拥有引擎,引擎不拥有飞机。
  2. It easily supports planes with different configurations of engines (one, three, four...) 它轻松支持具有不同引擎配置的飞机(一,三,四...)

As @APC said, Cyclic dependencies between Engine and Airplane is a bad design. 正如@APC所说,引擎与飞机之间的循环依赖关系是一个糟糕的设计。 But with the solution described below, Engine.Airplane_Owner_ID could be implemented only as logical back-link which not exist in Database table. 但是使用下面描述的解决方案,Engine.Airplane_Owner_ID只能实现为数据库表中不存在的逻辑反向链接。

Airplane.hbm.xml Airplane.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping">
<hibernate-mapping>
    <class name="Airplane" table="AIRPLANE">
        <id name="id" type="int" column="AIRPLANE_ID">
            <generator class="native"/>
        </id>
        <property name="name" column="AIRPLANE_NAME" type="string" length="250"/>
        <many-to-one name="rightEngine" class="Engine" cascade="save-update" unique="true"/>
        <many-to-one name="leftEngine" class="Engine" cascade="save-update" unique="true"/>
    </class>
</hibernate-mapping>

Engine.hbm.xml Engine.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping">
<hibernate-mapping>
    <class name="Engine" table="ENGINE">
        <id name="id" type="int" column="ENGINE_ID">
            <generator class="native"/>
        </id>
        <property name="name" column="ENGINE_NAME" type="string" length="250"/>
        <property name="position" column="ENGINE_POSITION" type="java.lang.Byte" />

        <one-to-one name="ownerAirplane" property-ref="rightEngine" />
    </class>
</hibernate-mapping>

Airplane.java Airplane.java

public class Airplane {
    private int id;
    private String name;

    private Engine rightEngine;
    private Engine leftEngine;

    public Airplane(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Engine getRightEngine() {
        return rightEngine;
    }

    public void setRightEngine(Engine rightEngine) {
        this.rightEngine = rightEngine;
    }

    public Engine getLeftEngine() {
        return leftEngine;
    }

    public void setLeftEngine(Engine leftEngine) {
        this.leftEngine = leftEngine;
    }

    @Override
    public String toString() {
        return "Airplane{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", rightEngline=" + (rightEngine == null ? null : rightEngine.getName()) +
                ", leftEngine=" + (leftEngine == null ? null : leftEngine.getName()) +
                '}';
    }
}

Engine.java Engine.java

public class Engine {

    private int id;
    private String name;
    private byte position;//0=left, 1=right
    private Airplane ownerAirplane;

    /**
     * @param name
     * @param position 0=left, 1=right
     */
    public Engine(String name, byte position) {
        this.name = name;
        this.position = position;
    }

    public Airplane getOwnerAirplane() {
        return ownerAirplane;
    }

    public void setOwnerAirplane(Airplane ownerAirplane) {
        this.ownerAirplane = ownerAirplane;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return 0=left, 1=right
     */
    public byte getPosition() {
        return position;
    }

    /**
     * @param position 0=left, 1=right
     */
    public void setPosition(byte position) {
        this.position = position;
    }


    @Override
    public String toString() {
        return "Engine{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", position=" + position +
                ", ownerAirplane=" + (ownerAirplane == null ? null : ownerAirplane.getName()) +
                '}';
    }
}

Main.java Main.java

 public static void main(final String[] args) throws Exception {

        Session session = ourSessionFactory.openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            Engine engineRight1 = new Engine("engineRight1", (byte) 1);
            Engine engineLeft1 = new Engine("engineLeft1", (byte) 0);
            Airplane airplane1 = new Airplane("Airplane1");

            Engine engineRight2 = new Engine("engineRight2", (byte) 1);
            Engine engineLeft2 = new Engine("engineLeft2", (byte) 0);
            Airplane airplane2 = new Airplane("Airplane2");

            Engine engineRight3 = new Engine("engineRight3", (byte) 1);
            Engine engineLeft3 = new Engine("engineLeft3", (byte) 0);
            Airplane airplane3 = new Airplane("Airplane3");

            engineLeft1.setOwnerAirplane(airplane1);
            engineRight1.setOwnerAirplane(airplane1);
            airplane1.setLeftEngine(engineLeft1);
            airplane1.setRightEngine(engineRight1);

            engineRight2.setOwnerAirplane(airplane2);
            airplane2.setRightEngine(engineRight2);
//            airplane2.setLeftEngine(engineLeft1);

            engineRight3.setOwnerAirplane(airplane3);
            airplane3.setLeftEngine(engineLeft3);

            session.save(airplane1);
            session.save(airplane2);
            session.save(airplane3);

            session.save(engineLeft1);
            session.save(engineLeft2);
            session.save(engineLeft3);
            session.save(engineRight1);
            session.save(engineRight2);
            session.save(engineRight3);

            transaction.commit();
        } catch (HibernateException e) {
            transaction.rollback();
            e.printStackTrace();
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM