membersound
membersound

Reputation: 86747

Cascade persist creates duplicate rows?

I'm creating a database entity object Order, and assign it to multiple entities of type BookingCode.

Problem: this creates a single order in db, which is fine. But the order itself has a @OneToOne OrderDescription, which occurs duplicate in the database.

@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;
}

Test:

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

Result: In my database I then have two OrderDescription entries, where I would expect only one, because I reused the same Order object and assigned it to different BookingCode objects.

Like:

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

As Order has a @OneToOne relation to OrderDescription And I even don't understand why the select using findOne() works correctly. Because in database I now have two OrderDescriptions that map to the same Order, but an Order can only have one of them.

Upvotes: 2

Views: 2862

Answers (2)

saurabh.in
saurabh.in

Reputation: 409

I had a similar issue where I had an Order obj and its variable prevOrder was referring to itself i.e. Order entity. And when I stored order, it would end up storing duplicate records for prevOrder.

I had the following code:

@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;
...

I tried various things including overriding equals and hashcode of Order, and adding a OneToOne mappedBy field 'nextOrder' etc. But noticed JPA didn't even call equals() to determine object's uniqueness. Ultimately I found out that JPA uses id field as the object's identifier and I wasn't storing the generated id while storing the object to a distrobuted cache. So it was all the time creating fresh objects during persistence.

Upvotes: 0

Fahad Fazil
Fahad Fazil

Reputation: 646

Persist the order first and then assign it to both bookingCode .

Upvotes: 3

Related Questions