JPA具有共享FK的多个ManyToOne

时间:2018-11-04 20:13:57

标签: hibernate jpa spring-data-jpa

我有2个具有相同类型的复合PK的实体(在下面的示例中,它是类 Shared )。我还有1个实体在Foo和Bar实体之间建立了联系。这是示例:

@Entity
class Shared {
    @Id private Long id;
}


@Entity
class Foo {
    @EmbeddedId private FooPK id;
}

@Embeddable
class FooPK implements Serializable {
    @ManyToOne
    @JoinColumn(name="shared_id")
    private Shared shared;
    private Long fooId;
}

@Entity
class Bar {
    @EmbeddedId private BarPK id;
}

@Embeddable
class BarPK implements Serializable {
    @ManyToOne
    @JoinColumn(name="shared_id")
    private Shared shared;
    private Long barId;
}

@Entity
class FooVsBar {
    @EmbeddedId private FooVsBarPK id;
}

@Embeddable
class FooVsBarPK implements Serializable {
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="id_shared_foo", referencedColumnName="shared_id"),
        @JoinColumn(name="id_foo", referencedColumnName="foo_id"),
    })
    private Foo foo;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="id_shared_bar", referencedColumnName="shared_id"),
        @JoinColumn(name="id_bar", referencedColumnName="bar_id"),
    })
    private Bar bar;
}

这样,FooVsBar表具有4列(2个FK),但是我想实现的是拥有3列:id_fooid_barid_shared作为Foo和Bar将始终与相同的Shared相关。因此,没有必要重复id_shared,它总是一样的。

更新: 这是UML数据库必须是什么样的。不幸的是,我无法更改表,我只需要将JPA映射到此模型。 enter image description here

2 个答案:

答案 0 :(得分:1)

像这样尝试:

@Entity
class FooVsBar {
    @EmbeddedId private FooVsBarPK id;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="shared_id", referencedColumnName="shared_id", 
                    insertable=false, updatable=false),
        @JoinColumn(name="foo_id", referencedColumnName="foo_id",
                    insertable=false, updatable=false)
    })
    private Foo foo;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="shared_id", referencedColumnName="shared_id",
                    insertable=false, updatable=false),
        @JoinColumn(name="bar_id", referencedColumnName="bar_id",
                    insertable=false, updatable=false)
    })
    private Bar bar;
}

@Embeddable
class FooVsBarPK implements Serializable {

    private Long sharedId;

    private Long fooId;

    private Long barId;
}

答案 1 :(得分:0)

最后,解决方案与@Vlad Mihalcea示例相同。这是完整的代码(省略了getter和setter的内容):

@Entity
public class Shared {
    @Id
    private Long id;
}

@Entity
public class Bar {
    @EmbeddedId
    private BarPK id;

    @MapsId("sharedId")
    @ManyToOne
    @JoinColumn(name="shared_id")
    private Shared shared;
}

@Embeddable
public class BarPK implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="shared_id")
    private Long sharedId;

    @Column(name="bar_id")
    private Long barId;
}

@Entity
public class Foo {
    @EmbeddedId
    private FooPK id;

    @MapsId("sharedId")
    @ManyToOne
    @JoinColumn(name="shared_id")
    private Shared shared;  
}

@Embeddable
public class FooPK implements Serializable {
    private static final long serialVersionUID = 1L;

    @Column(name="shared_id")
    private Long sharedId;

    @Column(name="foo_id")
    private Long fooId;
}

@Entity
public class FooVsBar {

    @EmbeddedId
    private FooVsBarPK id;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="shared_id", referencedColumnName="shared_id", insertable=false, updatable=false),
        @JoinColumn(name="foo_id", referencedColumnName="foo_id", insertable=false, updatable=false)
    })
    private Foo foo;

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="shared_id", referencedColumnName="shared_id", insertable=false, updatable=false),
        @JoinColumn(name="bar_id", referencedColumnName="bar_id", insertable=false, updatable=false)
    })
    private Bar bar;
}

@Embeddable
public class FooVsBarPK implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(name="shared_id")
    private Long sharedId;

    @Column(name="foo_id")
    private Long fooId;

    @Column(name="bar_id")
    private Long barId;
}