JPA сопоставление с не-первичным ключом. Название столбца в двух таблицах также различаются - PullRequest
0 голосов
/ 04 ноября 2019

Есть две таблицы БД, скажем 1. Таблица A с первичным ключом в качестве aId. A имеет столбец с именем orderNo. 2. Таблица B с первичным ключом в качестве bId. B имеет столбец с именем salesOrderNo.

A.orderNo такой же, как B.salesOrderNo, и, кроме того, для одной записи в таблице A, соответствующей определенному orderNo, в таблице B может быть много записей с одним и тем же salesOrderNo.

Как определить это отношение OneToMany (EntityA: EntityB).

Я пробовал следующее и столкнулся с проблемами:

@Entity
@Table(name = "A")
public class A implements Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "A_KEY")
    private String aId;

    @Column(name = "ORDER_NO")
    private String orderNo;

    @OneToMany
    @JoinColumn(referencedColumnName = "salesOrderNo")
    List<B> b;
}

@Entity
@Table(name = "B")
public class B implements Serializable{
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "B_KEY")
    private String bId;

    @Column(name="SALES_ORDER_NO")
    private String salesOrderNo;

    @ManyToOne
    @JoinColumn(referencedColumnName = "orderNo")
    @JsonIgnore
    private A a;
}

Ошибка, которую я вижу во времязапуск приложения:

Ошибка вызова метода init;Вложенное исключение: org.hibernate.MappingException: невозможно найти столбец с логическим именем: orderNo в org.hibernate.mapping.Table (A) и связанных с ним надставных и вторичных таблицах.

1 Ответ

0 голосов
/ 04 ноября 2019

В объекте A,

@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "SALES_ORDER_NO", referencedColumnName = "ORDER_NO")
List<B> b;

И в объекте B,

@ManyToOne
@JoinColumn(name = "SALES_ORDER_NO", referencedColumnName = "ORDER_NO", insertable = false, updatable = false)
@JsonIgnore
private A a;

Причина, по которой оба @JoinColumn выглядят одинаково, поскольку они представляют собой одно и то же отображение.

Из документации

Если объединение для сопоставления OneToOne или ManyToOne с использованием стратегии сопоставления внешнего ключа, столбец внешнего ключа находится в таблицеисходная сущность или встраиваемая.

Лучший способ понять отображение JPA - это подумать о структуре таблицы и SQL-запросе, который должен создать JPA. В вашем случае каждая строка B имеет ссылку на некоторую строку A. Но A не имеет никакого отношения к B. Таким образом, в таблице B будет иметь внешний ключ, в вашем случае SALES_ORDER_NO, который будет ссылаться на некоторый столбец в таблице A, в вашем случае ORDER_NO. Таким образом, независимо от того, куда вы положили @JoinColumn, вы должны правильно получить внешний ключ и ссылочный ключ.

Поскольку A не имеет внешнего ключа, вы можете удалить @JoinColumn из сущности A и обратитесь к отображению, выполненному в B следующим образом -


@OneToMany(fetch = FetchType.EAGER, mappedBy = "a")
List<B> b;

Чтобы увидеть, действительно ли оно отображает сущности правильно, я запросил обе сущности с помощью диспетчера сущностей, и он выдал следующие SQL-запросы для сущности A

    select
        a0_.a_key as a_key1_0_0_,
        a0_.order_no as order_no2_0_0_,
        b1_.sales_order_no as sales_or2_1_1_,
        b1_.b_key as b_key1_1_1_,
        b1_.b_key as b_key1_1_2_,
        b1_.sales_order_no as sales_or2_1_2_ 
    from
        a a0_ 
    left outer join
        b b1_ 
            on a0_.order_no=b1_.sales_order_no 
    where
        a0_.a_key=?

А для сущности B

    select
        b0_.b_key as b_key1_1_0_,
        b0_.sales_order_no as sales_or2_1_0_,
        a1_.a_key as a_key1_0_1_,
        a1_.order_no as order_no2_0_1_ 
    from
        b b0_ 
    left outer join
        a a1_ 
            on b0_.sales_order_no=a1_.order_no 
    where
        b0_.b_key=?

Что, кажется, соответствует вашему описанию.

...