У меня есть таблица с уникальным ограничением в одном поле, и я хочу настроить Hibernate EntityManager, чтобы она вставляла новую запись только в том случае, если такой записи уже нет и будет обновляться иначе.Hibernate: Вставка обновления с EntityManager
Мой POJO для таблицы выглядит выглядит так:
@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;
}
}
И я пытаюсь решить необходимые изменения с помощью этого кода:
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);
}
}
В журнале Spring, я вижу один дополнительный выберите:
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=?
Я думаю, это происходит потому, что я использую функцию слияния, но если я не ищу o bject id перед его объединением, слияние попытается вставить объект вместо его обновления. Есть ли способ просто обновить объект, не тестируя его в первую очередь?
И не связанный вопрос, SQL выглядит очень грязно. все это link0_.link_id as link_id1_0_
, они могут быть подавлены?
У вас были улучшения на этом? –
Нет, я проигнорировал спящий режим на данный момент и переключился на шаблоны – Dmitry