Java – hibernate saveorupdate() attempts to save when it should be updated

I have a hibernate entity named issueparticipant It basically describes the relationship between users and problems (similar to JIRA or bugzilla problems) It represents a many to many linked table in the database, which links the user ID to the problem ID, but also includes other information related to notification settings, so it is regarded as its own entity

I encountered a big problem when using userid and issueid as composite keys, so I created a composite key, which is a string (and varchar in Postgres database), which is formed as follows:

Now, I have a screen where users can edit all users related to the problem and edit notification settings In the controller class, I create an issueparticipants list as follows:

IssueParticipant participant = new IssueParticipant();
participant.setUser(accountUser);
participant.setIssue(issue);

So of course these are not managed by hibernate

Then in my Dao, I iterate over them and call saveOrUpdate (), expecting that if there is an issueparticipant with the same composite key in the database, it will be updated; Otherwise it will be inserted:

for (IssueParticipant participant : participants) {
        getCurrentSession().saveOrUpdate(participant);
        savedIds.add(participant.getIssueUserKey());
    }

(savedids is the list I'm maintaining so that later I'll know which issuepaarticipants I should delete from the database)

Instead of what I expected, I got an exception:

org.postgresql.util.PsqlException: ERROR: duplicate key value violates unique constraint "issue_participant_pkey"

This is my entity class, abbreviated as:

public class IssueParticipant extends Entity {

    private String issueUserKey;
    private Long issueId;
    private Long userId;

     // Edit: adding 'dateAdded' deFinition
    private Date dateAdded;
// ...

    // below may be null
    private SPUser user;
    private Issue issue;

    public static IssueParticipant nulledIssueParticipant() {
        IssueParticipant ip = new IssueParticipant();
        return ip;
    }
    public String getIssueUserKey() {
        return issueUserKey;
    }

    public void setIssueUserKey(String issueUserKey) {
        this.issueUserKey = issueUserKey;
    }

    public Long getId() {
        // currently meaningless
        return 0L;
    }

    public Long getIssueId() {
        return this.issueId;
    }

    public void setIssueId(Long issueId) {
        this.issueId = issueId;
        updateKey();
    }

    public Long getUserId() {
        return this.userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
        updateKey();
    }

    private void updateKey() {
        issueUserKey = getIssueId() + KEY_SEP + getUserId();
    }

    public SPUser getUser() {
        return user;
    }

    public void setUser(SPUser user) {
        this.user = user;
        setUserId(user.getId());
    }

    public Issue getIssue() {
        return issue;
    }

    public void setIssue(Issue issue) {
        this.issue = issue;
        setIssueId(issue.getId());
    }

// edit: adding 'dateAdded' methods
public Date getDateAdded() {
    return dateAdded;
}

public void setDateAdded(Date dateAdded) {
    this.dateAdded = dateAdded;
}

...

}

This is its HBM file:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping default-lazy="false">
    <class name="com.xxx.yyy.IssueParticipant" table="issue_participant">
        <id name="issueUserKey" column="issue_user_key" type="string">
            <generator class="assigned"/>
        </id> 
        <version name="dateAdded" column="date_added" type="timestamp" unsaved-value="null" />
        <property name="issueId" column="issue_id" />
        <many-to-one name="user" column="user_id" class="com.xxx.yyy.SPUser" not-null="true" cascade="none" />
        <property name="alertRSS" column="alert_RSS" type="boolean" />
        <property name="alertEmail" column="alert_email" type="boolean" />
        <property name="alertWeb" column="alert_web" type="boolean" />
        <property name="alertClient" column="alert_client" type="boolean" />

    </class>
</hibernate-mapping>

Actually, user_ issue_ Key is the primary key in the corresponding database table

In this case, I think the correct solution may be to use spring JDBC, but I really want to know what happened here What does anyone think? Thank you in advance

Solution

Saveorupdate() does not query the database to determine whether a given entity should be saved or updated It makes decisions based on the status of the entity as follows:

Therefore, as far as I know, in your case, the decision is based on the value of the dateadded field, so you need to keep it to distinguish between new instances and separated instances

You can also see:

> 11.7. Automatic state detection

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>