【问题标题】:Cascade persist creates duplicate rows?级联持续创建重复行?
【发布时间】:2016-06-28 10:28:37
【问题描述】:

我正在创建一个数据库实体对象Order,并将其分配给BookingCode 类型的多个实体。

问题:这会在 db 中创建一个订单,这很好。但是订单本身有一个@OneToOneOrderDescription,在数据库中出现重复。

@Entity
public class BookingCode {
    @Id
    private Long id;

    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DETACH})
    private Order order;
}

@Entity
public class Order {
    @Id
    private Long id;

    private String orderName;

    @OneToOne(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
    private OrderDescription description;
}

@Entity
public class OrderDescription {
    @Id
    private Long id;

    //for simplicity just one text element; of course multiple fields in real life
    private String text;

    @OneToOne
    private Order order;
}

测试:

Order order = new Order();
order.setOrderName("test");

OrderDescription d = new OrderDescription("testdescr");
d.setOrder(order);
order.setDescription(d);

List<BookingCodes> codes = new ArrayList<>();

BookingCode code = new BookingCode();
code.setOrder(order);
codes.add(order);

BookingCode code2 = new BookingCode();
code2.setOrder(order); //using the same offer entity!
codes.add(order2);

codes = dao.save(codes); //CrudRepository from Spring

dao.findOne(codes.get(0).getId()); //this works, find an order which has one of the OrderDescriptions

结果: 在我的数据库中,我有 两个 OrderDescription 条目,我希望只有一个,因为我重用了相同的 Order 对象并将其分配给不同的 BookingCode 对象。

喜欢:

table order_descrption:
1;"de";"testdescr";"123456"
2;"de";"testdescr";"123456"

因为OrderOrderDescription@OneToOne 关系 而且我什至不明白为什么使用findOne()select 可以正常工作。因为在数据库中我现在有两个OrderDescriptions 映射到同一个Order,但一个Order 只能有其中一个。

【问题讨论】:

  • 你有合适的 hashCode 和 equals 方法吗?
  • 我没有任何 hash 或 equals 方法。但是hibernate不应该能够检测到我将要保存相同的Order和相同的OrderDescription吗?
  • 没有适当的等号/哈希码实现。 JPA 对其工作方式非常挑剔。它将对象替换为托管对象,此时它们不再匹配。如果没有正确的 equals/hashcode 实现,hibernate 无法检测到这一点。因此建议首先保持顺序,然后再进行其他任何操作。

标签: java spring postgresql


【解决方案1】:

先保留订单,然后将其分配给两个 bookingCode 。

【讨论】:

  • 这行得通,谢谢。无论如何,我想知道是否仍然可以一次性保存这些对象。
  • order 应该有一个主键,以便识别订单是否相同
【解决方案2】:

我有一个类似的问题,我有一个 Order obj,它的变量 prevOrder 指的是它自己,即 Order 实体。当我存储订单时,它最终会为 prevOrder 存储重复的记录。

我有以下代码:

@Entity 
@Table(name = "orders")
public class Order implements Serializable {

@Id
@GeneratedValue(generator = "order_id_generator")
@SequenceGenerator(name = "order_id_generator", sequenceName = "order_id_sequence", allocationSize = 1)
@Column(name = "id", updatable = false, nullable = false)
private Long id;

@OneToOne(cascade = CascadeType.ALL, optional = true)
@JoinColumn(name = "previous_order_id", unique = true, updatable = false, referencedColumnName = "id")
private Order previousOrder;

@OneToOne(cascade = CascadeType.ALL, mappedBy = "previousOrder")
private Order nextOrder;
...

我尝试了各种方法,包括覆盖 Order 的 equals 和哈希码,以及添加 OneToOne mappedBy 字段 'nextOrder' 等。但注意到 JPA 甚至没有调用 equals() 来确定对象的唯一性。最终我发现 JPA 使用 id 字段作为对象的标识符 并且我在将对象存储到分布式缓存时没有存储生成的 id。因此,在持久化期间一直在创建新对象。

【讨论】:

    猜你喜欢
    • 2013-03-05
    • 1970-01-01
    • 2021-11-10
    • 2011-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    相关资源
    最近更新 更多