Problem saving object with composite key
pasmar17 Jun 16, 2008 12:42 PMHi!
I use Seam 2.0.2.SP1, jboss-4.2.2.GA and oracle 10i. There are my classes (all generated by Hibernate Tools 3.2.0.b9).
CLASS ACCOUNT:
@Entity @Table(name = "ACCOUNT") public class Account implements java.io.Serializable { private long progAccountId; private String userid; private String password; private String nome; private String cognome; private Date dataNascita; private Long userInsert; private Date dateInsert; private Long userModify; private Date dateModify; private Long userDelete; private Date dateDelete; private Date dateModifyPwd; private Set<SecurityLog> securityLogs = new HashSet<SecurityLog>(0); private Set<UtentiConnessi> utentiConnessis = new HashSet<UtentiConnessi>(0); private Set<AccountProfile> accountProfiles = new HashSet<AccountProfile>(0); //...other method @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "account") public Set<AccountProfile> getAccountProfiles() { return this.accountProfiles; } public void setAccountProfiles(Set<AccountProfile> accountProfiles) { this.accountProfiles = accountProfiles; } }
CLASS ACCOUNT-PROFILE:is a association table
@Entity @Table(name = "ACCOUNT_PROFILE") public class AccountProfile implements java.io.Serializable { private AccountProfileId id; private Account account; private Profile profile; private Long userInsert; private Date dateInsert; private Long userModify; private Date dateModify; private Long userDelete; private Date dateDelete; //...other method @EmbeddedId @AttributeOverrides( { @AttributeOverride(name = "progProfileId", column = @Column(name = "PROG_PROFILE_ID", nullable = false, precision = 10, scale = 0)), @AttributeOverride(name = "progAccountId", column = @Column(name = "PROG_ACCOUNT_ID", nullable = false, precision = 10, scale = 0)) }) public AccountProfileId getId() { return this.id; } public void setId(AccountProfileId id) { this.id = id; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PROG_ACCOUNT_ID", nullable = false, insertable = false, updatable = false) public Account getAccount() { return this.account; } public void setAccount(Account account) { this.account = account; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PROG_PROFILE_ID", nullable = false, insertable = false, updatable = false) public Profile getProfile() { return this.profile; } public void setProfile(Profile profile) { this.profile = profile; } }
CLASS ACCOUNT-PROFILE-ID: is the class ID of Account-Profile
@Embeddable public class AccountProfileId implements java.io.Serializable { private long progProfileId; private long progAccountId; public AccountProfileId() { } public AccountProfileId(long progProfileId, long progAccountId) { this.progProfileId = progProfileId; this.progAccountId = progAccountId; } @Column(name = "PROG_PROFILE_ID", nullable = false, precision = 10, scale = 0) public long getProgProfileId() { return this.progProfileId; } public void setProgProfileId(long progProfileId) { this.progProfileId = progProfileId; } @Column(name = "PROG_ACCOUNT_ID", nullable = false, precision = 10, scale = 0) public long getProgAccountId() { return this.progAccountId; } public void setProgAccountId(long progAccountId) { this.progAccountId = progAccountId; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof AccountProfileId)) return false; AccountProfileId castOther = (AccountProfileId) other; return (this.getProgProfileId() == castOther.getProgProfileId()) && (this.getProgAccountId() == castOther.getProgAccountId()); } public int hashCode() { int result = 17; result = 37 * result + (int) this.getProgProfileId(); result = 37 * result + (int) this.getProgAccountId(); return result; } }
I use the EntityHome class for Account and i add a method for insert a new Account, this is a portion:
Date currentDate = new Date(System.currentTimeMillis()); Account account =createInstance(); account.setUserid(username); account.setPassword(encryptPsw); account.setNome(firstName); account.setCognome(lastName); account.setDataNascita(dateBirth); account.setUserInsert(accountLogged.getProgAccountId()); account.setDateInsert(currentDate); account.setUserModify(accountLogged.getProgAccountId()); account.setDateModify(currentDate); account.setDateModifyPwd(currentDate); AccountProfile accountProfile; //profiles is a list of Profile binded by input for (Profile prof : profiles) { accountProfile = new AccountProfile(); AccountProfileId accProfID = new AccountProfileId(prof.getProgProfileId(), account.getProgAccountId()); accountProfile.setAccount(account); accountProfile.setProfile(prof); accountProfile.setId(accProfID); accountProfile.setUserInsert(accountLogged.getProgAccountId()); accountProfile.setDateInsert(currentDate); accountProfile.setUserModify(accountLogged.getProgAccountId()); accountProfile.setDateModify(currentDate); account.getAccountProfiles().add(accountProfile); }// for (Profile prof : profiles) setInstance(account); persist();
The id for Account class is assigned by a sequence on hibernate, so i don't know its value. So when i save the new account i have this error:
javax.persistence.PersistenceException: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [it.poste.pinats.security.ejb.entities.AccountProfile#it.poste.pinats.security.ejb.entities.AccountProfileId@5b0e]
I think that the problem is when i inizilized the id of the new account-profile:
AccountProfileId accProfID = new AccountProfileId(prof.getProgProfileId(), account.getProgAccountId());
because the id of account is 0 and it is no yet assigned by oracle sequence.
There is a way to configure the class so that the id is assigned by oracle sequence before saving?