簡體   English   中英

休眠:使用EntityManager插入更新

[英]Hibernate: Insert of Update with 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=?

我猜是因為我使用了合並功能,所以發生了,但是如果我在合並之前不搜索對象ID,則合並將嘗試插入對象而不是更新對象。 有沒有一種方法可以不先測試就更新對象?

和無關的問題,SQL看起來很混亂。 所有這些link0_.link_id as link_id1_0_ ,它們可以被抑制嗎?

懶惰的一對多關系導致了額外的連接。 除了對鏈接本身進行選擇之外,還會執行一條額外的選擇語句來加載集合(這是著名的N + 1問題的根源)。

並且,對於在更新之前執行的選擇,這似乎是實體分離時默認情況下休眠保持的方式。 如果要避免這種情況,則應使用其配置(有一個select-before-update屬性)或自己編寫一個更新查詢。 您也可以嘗試避免Spring分離Hibernate實體。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM