Problem saving object with composite key
pasmar17 Jun 17, 2008 4:42 AMHi!
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 inizialized 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?