Hibernate: Insert of Update with EntityManager
<p>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.</p>

<p>My POJO for the table looks looks this:</p>

<pre><code>@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&lt;Result&gt; 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&lt;Result&gt; getResults() {
        return results;
    }

    public void setResults(List&lt;Result&gt; 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;
    }
}
</code></pre>

<p>And I'm try to resolve the necessary changes through this code:</p>

<pre><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);
    }
}
</code></pre>

<p>In the Spring log, I see one additional select:</p>

<pre><code>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=?
</code></pre>

<p>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? </p>

<p>And unrelated question, the SQL's looks very messy. all these <code>link0_.link_id as link_id1_0_</code>, can they be suppressed? </p>