Reputation: 86747
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
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
Reputation: 646
Persist the order first and then assign it to both bookingCode .
Upvotes: 3