我在一个字段上有一个具有唯一约束的表,我想设置Hibernate EntityManager,这样只有在没有这样的记录时它才会插入新记录,并且会在其他地方进行更新。
我的表的POJO看起来像这样:
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);
}
}
我尝试通过以下代码解决必要的更改:
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=?
在Spring日志中,我看到另外一个选择:
link0_.link_id as link_id1_0_
我想,这是因为我使用了merge函数,但是如果我在合并之前没有搜索对象id,那么合并将尝试插入对象而不是更新它。有没有办法只更新对象而不先测试它?
和无关的问题,SQL看起来非常混乱。所有这些{{1}},它们能被压制吗?
答案 0 :(得分:0)
额外的加入是由于你懒惰的一对多关系。除了链接本身的选择之外,还会执行额外的select语句来加载集合(这是着名的N + 1问题的根源)。
并且,对于在更新之前执行的选择,当实体被分离时,它似乎是hibernate持久化by default的方式。如果你想避免它,你应该玩它的配置(有一个select-before-update
属性)或自己写一个更新查询。你也可以尝试避免Spring分离Hibernate实体。