Hibernate:使用EntityManager插入更新

时间:2016-02-21 13:01:25

标签: java mysql spring hibernate jpa

我在一个字段上有一个具有唯一约束的表,我想设置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}},它们能被压制吗?

1 个答案:

答案 0 :(得分:0)

额外的加入是由于你懒惰的一对多关系。除了链接本身的选择之外,还会执行额外的select语句来加载集合(这是着名的N + 1问题的根源)。

并且,对于在更新之前执行的选择,当实体被分离时,它似乎是hibernate持久化by default的方式。如果你想避免它,你应该玩它的配置(有一个select-before-update属性)或自己写一个更新查询。你也可以尝试避免Spring分离Hibernate实体。