0 Replies Latest reply on Jun 16, 2008 12:42 PM by pasmar17

    Problem saving object with composite key

    pasmar17

      Hi!


      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?