Issue
I have two tables: Customer (parent) and Orders (child). Both are mapped by
customerId (customer_id :unique key, in both parent & child).
In code in some Impl class, I'm saving data after setting fields in entities,
...
String status = someObject.getStatus();
customer.setLastPurchageStatus(status);
order.setStatus(status);
....
and saving it with built-in 'save
' as:
try {
LOGGER.info("Customer status:{}, Order statu:{}", customer.getLastPurchageStatus(), customer.getOrder().getStatus());
customerRepo.save(customer);
} catch(Exception e) {
LOGGER.info(e);
}
The above LOGGER.info line logged same status, but when seen in tables after 5 min, Customer table was with old values while Order table was updated with corrected value. This behavior happens only for 5-6% of transactions. I did not see any exceptions in Logs.
Entities are like this:
Customer
@TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class), })
@Entity
@Table(name = "customer")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Customer implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -395898276179285945L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "customer_seq")
private long customerSeq;
@Column(name = "customer_id")
private String customerId;
@Column(name = "last_purchase_status")
private String lastPurchageStatus;
@JsonManagedReference
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, mappedBy = "Customer")
private Set<Order> order;
Order
@Entity
@Table(name = "order")
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Order implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -4250363507869746908L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "order_seq")
private String orderSeq;
@Column(name = "order_id")
private String orderId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_seq", referencedColumnName = "customer_seq")
@JsonBackReference
private Customer customer;
@Column(name = "customer_id")
private String customerId;
@Column(name = "status")
private String status;
.......
...other getters/setters
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_seq", referencedColumnName = "customer_seq")
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
.....
Any help ??
Solution
The effect you might see here is called the "lost update" phenomenon, which you can protect yourself from by using optimistic locking with a @Version Long version
field. Read up on the topic on the internet and you will probably see very fast how a concurrent transaction that updates customer rows could cause this.
Answered By - Christian Beikov
Answer Checked By - Willingham (JavaFixing Volunteer)