Вопрос по java – Объединение в несколько столбцов в Hibernate / JPA Аннотации

21

У меня есть две сущности, к которым я хотел бы присоединиться через несколько столбцов. Эти столбцы являются общими@Embeddable объект, который является общим для обеих сущностей. В приведенном ниже примереFoo может иметь только одинBar ноBar может иметь несколькоFooс (гдеAnEmbeddableObject это уникальный ключ дляBar). Вот пример:

@Entity
@Table(name = "foo")
public class Foo {
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "seqGen")
    @SequenceGenerator(name = "seqGen", sequenceName = "FOO_ID_SEQ", allocationSize = 1)
    private Long id;
    @Embedded
    private AnEmbeddableObject anEmbeddableObject;
    @ManyToOne(targetEntity = Bar.class, fetch = FetchType.LAZY)
    @JoinColumns( {
        @JoinColumn(name = "column_1", referencedColumnName = "column_1"),
        @JoinColumn(name = "column_2", referencedColumnName = "column_2"),
        @JoinColumn(name = "column_3", referencedColumnName = "column_3"),
        @JoinColumn(name = "column_4", referencedColumnName = "column_4")
    })
    private Bar bar;

    // ... rest of class
}

И Бар класс:

@Entity
@Table(name = "bar")
public class Bar {
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "seqGen")
    @SequenceGenerator(name = "seqGen", sequenceName = "BAR_ID_SEQ", allocationSize = 1)
    private Long id;
    @Embedded
    private AnEmbeddableObject anEmbeddableObject;

    // ... rest of class
}

Наконец тоAnEmbeddedObject учебный класс:

@Embeddable
public class AnEmbeddedObject {
    @Column(name = "column_1")
    private Long column1;
    @Column(name = "column_2")
    private Long column2;
    @Column(name = "column_3")
    private Long column3;
    @Column(name = "column_4")
    private Long column4;

    // ... rest of class
}

Очевидно, что схема плохо нормализована, это ограничение, котороеAnEmbeddedObjectполя повторяются в каждой таблице.

У меня проблема в том, что я получаю эту ошибку при попытке запустить Hibernate:

org.hibernate.AnnotationException: referencedColumnNames(column_1, column_2, column_3, column_4) of Foo.bar referencing Bar not mapped to a single property

Я попытался пометить JoinColumns не для вставки и обновления, но безуспешно. Есть ли способ выразить это с помощью аннотаций Hibernate / JPA?

Что делать, если вы удалите встраиваемый объект изFoo? siebz0r

Ваш Ответ

3   ответа
9

у меня нет идей. Таким образом, вы получите 4 столбца в обеих таблицах (какBar владеет ими иFoo использует их для ссылкиBar) и сгенерированные идентификаторы в обоих объектах. Набор из 4 столбцов должен быть уникальным вBar таким образом, отношение «многие к одному» не становится отношением «многие ко многим».

@Embeddable
public class AnEmbeddedObject
{
    @Column(name = "column_1")
    private Long column1;
    @Column(name = "column_2")
    private Long column2;
    @Column(name = "column_3")
    private Long column3;
    @Column(name = "column_4")
    private Long column4;
}

@Entity
public class Foo
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "seqGen")
    @SequenceGenerator(name = "seqGen", sequenceName = "FOO_ID_SEQ", allocationSize = 1)
    private Long id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
        @JoinColumn(name = "column_1", referencedColumnName = "column_1"),
        @JoinColumn(name = "column_2", referencedColumnName = "column_2"),
        @JoinColumn(name = "column_3", referencedColumnName = "column_3"),
        @JoinColumn(name = "column_4", referencedColumnName = "column_4")
    })
    private Bar bar;
}

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {
    "column_1",
    "column_2",
    "column_3",
    "column_4"
}))
public class Bar
{
    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "seqGen")
    @SequenceGenerator(name = "seqGen", sequenceName = "BAR_ID_SEQ", allocationSize = 1)
    private Long id;
    @Embedded
    private AnEmbeddedObject anEmbeddedObject;
}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded bowsie
Error: User Rate Limit Exceeded bowsie
Error: User Rate Limit ExceededFooError: User Rate Limit ExceededBarError: User Rate Limit ExceededBarError: User Rate Limit ExceededFooError: User Rate Limit Exceeded
Error: User Rate Limit ExceededBarError: User Rate Limit ExceededFooError: User Rate Limit ExceededFooError: User Rate Limit Exceeded
5

Документация Hibernate:

Note that when using referencedColumnName to a non primary key column, the associated class has to be Serializable. Also note that the referencedColumnName to a non primary key column has to be mapped to a property having a single column (other cases might not work). (emphasis added)

Так что если вы не хотите делатьAnEmbeddableObject Идентификатор Bar, тогда Hibernate не собирается лениво, автоматически извлекает Bar для вас. Конечно, вы все еще можете использовать HQL для написания запросов, которые присоединяются кAnEmbeddableObject, но вы теряете автоматическую выборку и обслуживание жизненного цикла, если вы настаиваете на использовании многоколоночного не первичного ключа для Bar.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded bowsie
Error: User Rate Limit Exceedednot mapped to a single propertyError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
11

foo и boo на основе 3 разных столбцов. Обратите внимание, что в моем случае 3 общих столбца не являются первичными ключами.

то есть сопоставление один к одному на основе 3 разных столбцов

@Entity
@Table(name = "foo")
public class foo implements Serializable
{
    @Column(name="foocol1")
    private String foocol1;
    //add getter setter
    @Column(name="foocol2")
    private String foocol2;
    //add getter setter
    @Column(name="foocol3")
    private String foocol3;
    //add getter setter
    private Boo boo;
    private int id;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "brsitem_id", updatable = false)
    public int getId()
    {
        return this.id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
    @OneToOne
    @JoinColumns(
    {
        @JoinColumn(updatable=false,insertable=false, name="foocol1", referencedColumnName="boocol1"),
        @JoinColumn(updatable=false,insertable=false, name="foocol2", referencedColumnName="boocol2"),
        @JoinColumn(updatable=false,insertable=false, name="foocol3", referencedColumnName="boocol3")
    }
    )
    public Boo getBoo()
    {
        return boo;
    }
    public void setBoo(Boo boo)
    {
        this.boo = boo;
    }
}





@Entity
@Table(name = "boo")
public class Boo implements Serializable
{
    private int id;
    @Column(name="boocol1")
    private String boocol1;
    //add getter setter
    @Column(name="boocol2")
    private String boocol2;
    //add getter setter
    @Column(name="boocol3")
    private String boocol3;
    //add getter setter
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "item_id", updatable = false)
    public int getId()
    {
        return id;
    }
    public void setId(int id)
    {
        this.id = id;
    }
}
Error: User Rate Limit Exceeded

Похожие вопросы