Hibernate saveOrUpdate() versucht zu speichern, wenn Sie es aktualisieren sollten

Ich habe eine Hibernate-Entität namens IssueParticipant. Es ist im Grunde beschreibt die Beziehung zwischen einem Benutzer und einem Problem (und das ist wie ein JIRA oder Bugzilla Problem). Es stellt eine Art von viele-zu-viele-Verknüpfung Tabelle in der Datenbank, die Verknüpfung Benutzer-ID, um eine Problem-ID, aber es enthält auch andere Informationen in Bezug auf Benachrichtigungs-Einstellungen, und so wird es behandelt, als eigene Entität.

Ich hatte riesige Probleme bei der Verwendung der userId und issueId als einen zusammengesetzten Schlüssel, so habe ich einen Klebeprozess der key ist ein String (und varchar in die postgres-Datenbank), die gebildet ist: _.

Nun, ich habe einen Bildschirm, auf dem ein Benutzer Bearbeiten können alle Benutzer im Zusammenhang mit einem Problem, während auch das Bearbeiten der Benachrichtigungseinstellungen. In einer controller-Klasse die ich erstellen Sie eine Liste der IssueParticipants wie diese:

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

So sind diese natürlich nicht geschafft, die von Hibernate an dieser Stelle.

Dann in meinem DAO ich Durchlaufen Sie, und rufen Sie saveOrUpdate(), in der Erwartung, dass, wenn ein IssueParticipant mit dem gleichen synthetischen Schlüssel in der Datenbank vorhanden, wird es aktualisiert, ansonsten wird eingefügt:

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

(savedIds ist eine Liste, die ich bin Pflege, so dass ich später wissen, was IssueParticipants ich sollte aus der Datenbank löschen).

Statt, was ich erwarte, wenn ich eine Ausnahme:

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

Hier ist meine entity-Klasse, abgekürzt:

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;
}

...

}

Hier ist Ihre hbm-Datei:

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

Und in der Tat user_issue_key ist der Primärschlüssel in der entsprechenden Datenbank-Tabelle.

Fühle ich mich wie die richtige Lösung könnte nur sein, zu verwenden SpringJDBC in diesem Fall, aber ich möchte wirklich gerne herausfinden, was hier Los ist. Jemand irgendwelche Gedanken? Vielen Dank im Voraus.

InformationsquelleAutor Dave Taubler | 2012-06-06
Schreibe einen Kommentar