I have a table with unique constraint on the one field and I want to setup Hibernate EntityManager so it would insert new record only if there is no such record already and will update otherways.
My POJO for the table looks looks this:
@Entity
@Table(name = "links", uniqueConstraints = {
@UniqueConstraint(columnNames = "link", name = "uk_link")
})
public class Link {
private long linkId;
private String link;
private String data;
private String metadata;
private List<Result> results;
@Id
@Column(name="link_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
public long getLinkId() {
return linkId;
}
public void setLinkId(long linkId) {
this.linkId = linkId;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getMetadata() {
return metadata;
}
public void setMetadata(String metadata) {
this.metadata = metadata;
}
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "link")
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
@Override
public String toString() {
return "Link [linkId=" + linkId + ", link=" + link + ", data=" + data + ", metadata=" + metadata + "]";
}
public boolean isDataEquals(String data) {
if (this.data == null) {
if (data != null)
return false;
} else if (!this.data.equals(data))
return false;
return true;
}
public boolean isMetadataEquals(String metadata) {
if (this.metadata == null) {
if (metadata != null)
return false;
} else if (!this.metadata.equals(metadata))
return false;
return true;
}
}
And I'm try to resolve the necessary changes through this code:
public Link selectByLink(String link) {
return entityManager
.createQuery("select l from Link l WHERE l.link = :link", Link.class)
.setParameter("link", link)
.getSingleResult();
}
public void insert(Link link) {
this.entityManager.persist(link);
}
public Link update(Link link) {
return this.entityManager.merge(link);
}
public void save(Link link) {
if (link.getLinkId() == 0) {
Link _existing = selectByLink(link.getLink());
if (null != _existing) {
link.setLinkId(_existing.getLinkId());
if (!_existing.isDataEquals(link.getData()) ||
!_existing.isMetadataEquals(link.getMetadata())) {
update(link);
}
} else
insert(link);
}
}
In the Spring log, I see one additional select:
Hibernate: select link0_.link_id as link_id1_0_, link0_.data as data2_0_, link0_.link as link3_0_, link0_.metadata as metadata4_0_ from links link0_ where link0_.link=?
Hibernate: select link0_.link_id as link_id1_0_1_, link0_.data as data2_0_1_, link0_.link as link3_0_1_, link0_.metadata as metadata4_0_1_, results1_.link_id as link_id1_1_3_, results1_.text_id as text_id2_1_3_, results1_.link_id as link_id1_1_0_, results1_.text_id as text_id2_1_0_, results1_.found as found3_1_0_, results1_.level as level4_1_0_ from links link0_ left outer join results results1_ on link0_.link_id=results1_.link_id where link0_.link_id=?
Hibernate: update links set data=?, link=?, metadata=? where link_id=?
I guess, it happens because I use merge function, but if I do not search for the object id prior merging it, the merge will try to insert object instead of updating it. Is there a way to just update the object without testing it first?
And unrelated question, the SQL's looks very messy. all these link0_.link_id as link_id1_0_
, can they be suppressed?