#jpa #glassfish #entity #one-to-many #duplicates
#jpa #glassfish #объект #один ко многим #дубликаты
Вопрос:
старое описание проблемы устарело
@unwichtich спасибо за ваш совет, он помог избавиться от этой неприятной ошибки.
У меня есть объекты:
@Entity
@XmlRootElement
@Table(name="WAITERENTITY")
public class WaiterEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.EAGER)
@JoinColumn(name = "waiter_id")
private List<OrderEntity> orders = new ArrayList<>();
{plus usual setters and getters}
}
и
@Entity
@XmlRootElement
@Table(name="ORDERENTITY")
public class OrderEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long orderNumber;
@ManyToOne (cascade = CascadeType.ALL)
@JoinColumn (name = "table_id")
private TableEntity table_;
private int sumOfMoney = 0;
private boolean finalized = false;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private List<OrderItemEntity> orderItems = new ArrayList<>();
@ManyToOne (cascade = CascadeType.ALL)
@JoinColumn (name = "waiter_id")
private WaiterEntity waiter;
{plus usual setters and getters}
}
Но основная проблема остается. В базе данных все так, как должно быть:
<waiterEntities>
<waiterEntity>
<id>9</id>
<name>Jack Marston #499</name>
</waiterEntity>
<waiterEntity>
<id>10</id>
<name>Abigail Marston</name>
</waiterEntity>
</waiterEntities>
<orderEntities>
<orderEntity>
<finalized>false</finalized>
<orderNumber>12</orderNumber>
<sumOfMoney>0</sumOfMoney>
<waiter>
<id>9</id>
<name>Jack Marston #499</name>
</waiter>
</orderEntity>
</orderEntities>
Но @OneToMany
отношение WaiterEntity
возвращает только пустой список при waiter.getOrders()
вызове.
Метод, который создает новый OrderEntity
, следующий:
public void create(OrderEntity e) {
WaiterEntity waiter = em.find(WaiterEntity.class, e.getWaiter().getId());
if (waiter != null) {
(1) e.setWaiter(waiter);
em.persist(e);
System.out.println("after persist:n" e);
(2) //waiter.getOrders().add(e);
(3) //em.merge(waiter);
}
}
Редактировать: я наблюдал очень странное поведение. Во-первых, если строки, отмеченные (2)
и (3)
, не прокомментированы, OrderEntity
вообще не будут сохраняться. Во-вторых, только следующих внешних операторов будет достаточно, чтобы GlassFish сохранял OrderEntity
:
WaiterBean waiter = client.findByNameSingle(WaiterBean.class, "John Marston");
client.create(new OrderBean(waiter));
Где create получит уникальный идентификатор соответствующего WaiterEntity
объекта из базы данных. С другой стороны, an OrderEntity
не будет сохранен, если WaiterEntity
идентификатор не известен, как, например, в:
client.create(new OrderBean(new WaiterBean("Hans")));
потому что этот новый объект не получен из базы данных. При закомментировании строки, отмеченной (1), появляется поведение strage: первый оператор с предыдущим получением соответствующего WaiterEntity
из базы данных не будет работать, но второй оператор, который не получает ничего WaiterEntity
из базы данных, будет работать и создаст OrderEntity
запись в базе данных. Мне действительно трудно это понять.
Две прокомментированные строки (2)
и (3)
должны гарантировать, что WaiterEntity
он знает свои OrderEntity
s для последующего извлечения. Но единственное, что делают эти две строки (или одна из них, я тоже пробовал), это предотвращение сохранения любого OrderEntity
объекта в базе данных. Он просто ничего не сделает, и никаких дальнейших ошибок не сообщается, что сводит меня с ума…
Есть идеи? Заранее спасибо!
Ответ №1:
Просто предположим, что вы добавляете неправильный OrderEntity
экземпляр. Если вы передаете экземпляр объекта em.merge()
EntityManager
в, создается новый экземпляр вашего объекта, копирует состояние из предоставленного объекта и делает новую копию управляемой. Вы должны использовать новую копию в любых дальнейших действиях в отношении этого объекта.
В коде:
public void create(OrderEntity e) {
WaiterEntity waiter = em.find(WaiterEntity.class, e.getWaiter().getId());
e = em.merge(e);
if (waiter != null) waiter.getOrders().add(e);
}
Комментарии:
1. Спасибо! Это немного помогает. Я обновил описание своей проблемы.