Reputation: 2113
In my application, I have a tender entity.
@Entity
@Table(name = "tender")
public class Tender {
@Id
@Column(name = "tender_id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
@OneToMany(mappedBy="tender", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JsonIgnoreProperties("tender")
private List<TenderAddress> addresses;
// constructors and getters and setters
// I am showing the setter for Address since it is customized for my requirement
public void setAddresses(List<TenderAddress> addresses) {
this.addresses = addresses;
for (TenderAddress tenderAddress : addresses) {
tenderAddress.setTender(this);
}
}
}
My TenderAddress
entity looks like this.
@Entity
@Table(name = "tender_address")
public class TenderAddress {
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="tender_id")
@JsonIgnoreProperties("addresses")
private Tender tender;
@Column(name = "address", nullable = false)
private String address;
// constructors
//getters and setters
}
Everything worked fine until I started testing the update operation.
This is my update method.
@Transactional
public Tender updateTender(Tender tender) {
Tender t = entityManager.find(Tender.class, tender.getId());
t.setName(tender.getName());
t.setDescription(tender.getDescription());
t.setAddresses(tender.getAddresses());
entityManager.merge(t);
entityManager.flush();
return findById(t.getId());
}
name and description are updated fine. What I thought how the addresses would get updated is, it will edit the current record in the relevant database table. But what happened was, it inserted a new record into the table with out editing the already existing record. In fact, I thought JPA looks after that it self.
So, my question now is, do I have to merge the address table explicitly when merging the tender table? If so, how it should be done?
Upvotes: 0
Views: 3515
Reputation: 21113
One question to ask is whether anything else will ever have an association to a TenderAddress
?
If the answer to your question is yes, then you'll have to do an iterative update of the list based on some natural key and not the database identifier. This is because your incoming list could be a combination of new and updated entries and should be merged in that particular way.
If the answer to your question is no, then you could rework the annotations of the mapping and accomplish what you thought would work. Rather than treat TenderAddress
as an entity type, lets change it to be considered an @Embeddable
and place it inside an @ElementCollection
as shown below:
@Entity
public class Tender {
@ElementCollection
private Set<TenderAddress> addresses;
}
@Embeddable
public class TenderAddress {
}
In this case, you can now safely replace the entire collection of TenderAddress
and Hibernate will basically perform a bulk delete from the collection table based on the Tender
primary key and then will reinsert all the new rows from the new list, which will work with the code which you've presented in your question.
Upvotes: 1