0 Replies Latest reply on Jun 17, 2008 4:42 AM 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 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?