#java #hibernate #jpa
#java #спящий режим #jpa
Вопрос:
У меня есть эти объекты (ненужные столбцы удалены для краткости)
Порядок
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL, optional = false)
private Shipment shipment;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Shipment getShipment() {
return shipment;
}
public void setShipment(Shipment shipment) {
this.shipment = shipment;
this.shipment.setOrder(this);
}
}
Пересылка
@Entity
@Table(name = "shipments")
public class Shipment {
@Id
@Column(name = "order_id")
private int id;
@OneToOne
@MapsId
private Order order;
@OneToOne(mappedBy = "shipment", cascade = CascadeType.ALL, optional = false)
private ShippingAddress shippingAddress;
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public ShippingAddress getShippingAddress() {
return shippingAddress;
}
public void setShippingAddress(ShippingAddress shippingAddress) {
this.shippingAddress = shippingAddress;
this.shippingAddress.setShipment(this);
}
}
Адрес доставки
@Entity
@Table(name = "shipping_address")
public class ShippingAddress {
@Id
@Column(name = "shipment_id")
private int id;
@OneToOne
@MapsId("shipment_id")
private Shipment shipment;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Shipment getShipment() {
return shipment;
}
public void setShipment(Shipment shipment) {
this.shipment = shipment;
}
}
Проблема возникает, когда я пытаюсь сохранить новое Order
. Как вы можете видеть из журналов, Hibernate правильно устанавливает значения для объектов Order
and Shipment
, но присваивает 0
shipment_id
столбцу in shipping_address
, что, конечно, вызывает конфликт FK .
Я считаю, что использую @MapsId
правильно, потому что, как я уже сказал, это работает для Order
Shipment
отношений and , но, похоже, не работает для Shipment
and ShippingAddress
.
Это журналы
2021-01-14 14:25:56,563 DEBUG [http-nio-8080-exec-3] org.hibernate.SQL: insert into orders (branch_office, coupon_code, customer_id, external_id, increment_id, interests, origin_channel, store_id, subtotal, total, total_discount, total_qty_ordered) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [1] as [VARCHAR] - [null]
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [2] as [VARCHAR] - [null]
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [3] as [INTEGER] - [20]
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [4] as [VARCHAR] - [5501505642]
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [5] as [VARCHAR] - [5501505642]
2021-01-14 14:25:56,564 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [6] as [NUMERIC] - [0.0000]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [7] as [VARCHAR] - [store]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [8] as [INTEGER] - [55]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [9] as [NUMERIC] - [2270.0000]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [10] as [NUMERIC] - [1580]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [11] as [NUMERIC] - [690]
2021-01-14 14:25:56,565 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [12] as [INTEGER] - [3]
2021-01-14 14:25:56,621 DEBUG [http-nio-8080-exec-3] org.hibernate.SQL: insert into shipments (carrier_id, pickup_id, shipment_id, shipping_cost, order_id) values (?, ?, ?, ?, ?)
2021-01-14 14:25:56,621 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [1] as [INTEGER] - [19]
2021-01-14 14:25:56,622 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [2] as [INTEGER] - [19]
2021-01-14 14:25:56,622 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [3] as [INTEGER] - [null]
2021-01-14 14:25:56,622 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [4] as [NUMERIC] - [0.0]
2021-01-14 14:25:56,622 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [5] as [INTEGER] - [20]
2021-01-14 14:25:56,623 DEBUG [http-nio-8080-exec-3] org.hibernate.SQL: insert into shipping_address (city, country_code, province_id, street_name, street_number, zip_code, shipment_id) values (?, ?, ?, ?, ?, ?, ?)
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [1] as [VARCHAR] - [Vicente López]
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [2] as [VARCHAR] - [AR]
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [3] as [INTEGER] - [21]
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [4] as [VARCHAR] - [ramon melgar,Nro 8170]
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [5] as [VARCHAR] - []
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [6] as [VARCHAR] - [1638]
2021-01-14 14:25:56,624 TRACE [http-nio-8080-exec-3] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [7] as [INTEGER] - [0]
Как вы можете видеть на последней вставке, Hibernate пытается вставить 0 вместо shipment_id
.
Я чего-то не понимаю?
Комментарии:
1. Вы никогда не должны использовать примитивные (ненулевые) типы для
@Id
. Переключите егоInteger
и посмотрите, исправит ли это.2. @chrylis-осторожно оптимистично — С точки зрения корректности, почему я не должен использовать примитивы для
@Id
?3. Поскольку примитив не способен содержать значение
null
to , явно означающее «неназначенный», и может возникнуть путаница, если существует реальный идентификатор 0.4. Вы поднимаете хороший вопрос. Я обновлю свои объекты, чтобы отразить это. Спасибо.
Ответ №1:
Согласно документации, значение @MapsId
аннотации относится к имени атрибута в составном ключе, которому соответствует атрибут отношения. Вы не используете составной ключ.
Итак, это:
@OneToOne
@MapsId("shipment_id")
private Shipment shipment;
следует исправить это:
@OneToOne
@MapsId
@JoinColumn(name = "shipment_id")
private Shipment shipment;
Я не могу найти доказательства в документации, но спящий режим игнорируется @Column(name = "shipment_id")
@Id
при использовании @MapsId
, поэтому вы должны указать имя столбца PK ShippingAddress
путем добавления @JoinColumn
.
Комментарии:
1. Проблема с этим подходом заключается в том, что Hibernate генерирует неправильное имя столбца. Он генерируется
order_shipment_id
, когда это должно бытьshipment_id
. Я исправил это, добавив@JoinColumn(name = "shipment_id", referencedColumnName = "order_id")
в@MapsId
inShippingAddress
, и это работает. Это правильно?2. Да, это правильно. Я не могу найти доказательства в документации. Но я столкнулся с этим позже. Спящий режим игнорируется
@Column(name = "shipment_id")
@Id
при использовании@MapsId
.3. Вы можете использовать
@JoinColumn(name = "shipment_id")
, поскольку это относится к PK целевого объекта4. Это сработало, даже лучше! Следует обновить ваш ответ, чтобы отразить это. Окончательный код должен быть:
@OneToOne @MapsId @JoinColumn(name = "shipment_id") private Shipment shipment;