4 Replies Latest reply on Apr 16, 2007 5:07 PM by jimk1723

    ManyToOne and Composite Keys

    jimk1723

      How do you annotate a ManyToOne relationship where the "Many" entitiy has a foreign key field that is also the member of a composite key?

      I am starting from Seam `generate-entities`, but the generated code fails when I create new instances of each entity in the same transaction - I'm getting foreign key violations on commit. It's clear the EmbeddedId class is not getting the id value.

        • 1. Re: ManyToOne and Composite Keys
          jimk1723

          Here's the code:

          package com.mydomain.myproject;
          
          // Generated Apr 13, 2007 6:45:10 PM by Hibernate Tools 3.2.0.b9
          
          import java.util.Date;
          import java.util.HashSet;
          import java.util.Set;
          import javax.persistence.CascadeType;
          import javax.persistence.Column;
          import javax.persistence.Entity;
          import javax.persistence.FetchType;
          import javax.persistence.GeneratedValue;
          import javax.persistence.Id;
          import javax.persistence.OneToMany;
          import javax.persistence.Table;
          import javax.persistence.Temporal;
          import javax.persistence.TemporalType;
          import org.hibernate.validator.NotNull;
          
          /**
           * Department generated by hbm2java
           */
          @Entity
          @Table(name = "DEPARTMENT")
          public class Department implements java.io.Serializable {
          
           private long departmentId;
          
           private Set<DepartmentStrings> departmentStringses = new HashSet<DepartmentStrings>(
           0);
          
           public Department() {
           }
          
           public Department(long departmentId) {
           this.departmentId = departmentId;
           }
          
           public Department(long departmentId,
           Set<DepartmentStrings> departmentStringses) {
           this.departmentId = departmentId;
          
           this.departmentStringses = departmentStringses;
           }
          
           @Id
           @Column(name = "DEPARTMENT_ID", unique = true, nullable = false, precision = 16, scale = 0)
           @NotNull
           @GeneratedValue
           public long getDepartmentId() {
           return this.departmentId;
           }
          
           public void setDepartmentId(long departmentId) {
           this.departmentId = departmentId;
           }
          
           @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "department")
           public Set<DepartmentStrings> getDepartmentStringses() {
           return this.departmentStringses;
           }
          
           public void setDepartmentStringses(
           Set<DepartmentStrings> departmentStringses) {
           this.departmentStringses = departmentStringses;
           }
          
          }
          


          package com.mydomain.myproject;
          // Generated Apr 13, 2007 6:45:10 PM by Hibernate Tools 3.2.0.b9
          
          import javax.persistence.AttributeOverride;
          import javax.persistence.AttributeOverrides;
          import javax.persistence.Column;
          import javax.persistence.EmbeddedId;
          import javax.persistence.Entity;
          import javax.persistence.FetchType;
          import javax.persistence.JoinColumn;
          import javax.persistence.ManyToOne;
          import javax.persistence.Table;
          import org.hibernate.validator.Length;
          import org.hibernate.validator.NotNull;
          
          /**
           * DepartmentStrings generated by hbm2java
           */
          @Entity
          @Table(name = "DEPARTMENT_STRINGS")
          public class DepartmentStrings implements java.io.Serializable {
          
           private DepartmentStringsId id;
           private Department department;
           private String name;
          
           public DepartmentStrings() {
           }
          
           public DepartmentStrings(DepartmentStringsId id, Department department) {
           this.id = id;
           this.department = department;
           }
           public DepartmentStrings(DepartmentStringsId id, Department department,
           String name) {
           this.id = id;
           this.department = department;
           this.name = name;
           }
          
           @EmbeddedId
           @AttributeOverrides({
           @AttributeOverride(name = "departmentId", column = @Column(name = "DEPARTMENT_ID", nullable = false, precision = 16, scale = 0)),
           @AttributeOverride(name = "langCode", column = @Column(name = "LANG_CODE", nullable = false, length = 5))})
           @NotNull
           public DepartmentStringsId getId() {
           return this.id;
           }
          
           public void setId(DepartmentStringsId id) {
           this.id = id;
           }
           @ManyToOne(fetch = FetchType.LAZY)
           @JoinColumn(name = "DEPARTMENT_ID", nullable = false, insertable = false, updatable = false)
           @NotNull
           public Department getDepartment() {
           return this.department;
           }
          
           public void setDepartment(Department department) {
           this.department = department;
           }
          
           @Column(name = "NAME", length = 4000)
           @Length(max = 4000)
           public String getName() {
           return this.name;
           }
          
           public void setName(String name) {
           this.name = name;
           }
          
          }
          


          package com.mydomain.myproject;
          // Generated Apr 13, 2007 6:45:10 PM by Hibernate Tools 3.2.0.b9
          
          import javax.persistence.Column;
          import javax.persistence.Embeddable;
          import org.hibernate.validator.Length;
          import org.hibernate.validator.NotNull;
          
          /**
           * DepartmentStringsId generated by hbm2java
           */
          @Embeddable
          public class DepartmentStringsId implements java.io.Serializable {
          
           private long departmentId;
           private String langCode;
          
           public DepartmentStringsId() {
           }
          
           public DepartmentStringsId(long departmentId, String langCode) {
           this.departmentId = departmentId;
           this.langCode = langCode;
           }
          
           @Column(name = "DEPARTMENT_ID", nullable = false, precision = 16, scale = 0)
           @NotNull
           public long getDepartmentId() {
           return this.departmentId;
           }
          
           public void setDepartmentId(long departmentId) {
           this.departmentId = departmentId;
           }
          
           @Column(name = "LANG_CODE", nullable = false, length = 5)
           @NotNull
           @Length(max = 5)
           public String getLangCode() {
           return this.langCode;
           }
          
           public void setLangCode(String langCode) {
           this.langCode = langCode;
           }
          
           public boolean equals(Object other) {
           if ((this == other))
           return true;
           if ((other == null))
           return false;
           if (!(other instanceof DepartmentStringsId))
           return false;
           DepartmentStringsId castOther = (DepartmentStringsId) other;
          
           return (this.getDepartmentId() == castOther.getDepartmentId())
           && ((this.getLangCode() == castOther.getLangCode()) || (this
           .getLangCode() != null
           && castOther.getLangCode() != null && this
           .getLangCode().equals(castOther.getLangCode())));
           }
          
           public int hashCode() {
           int result = 17;
          
           result = 37 * result + (int) this.getDepartmentId();
           result = 37 * result
           + (getLangCode() == null ? 0 : this.getLangCode().hashCode());
           return result;
           }
          
          }
          




          • 2. Re: ManyToOne and Composite Keys

            Sorry, but your ERM does not make any sense. What are you trying to achieve?

            Regards

            Felix

            • 3. Re: ManyToOne and Composite Keys
              jimk1723

               

              Sorry, but your ERM does not make any sense. What are you trying to achieve?


              The example is a bit contrived; I was simply modeling a Department table that has an association to a DeparmentStrings table which stores a localized name of the department, i.e. the composite key of DeparmentStrings would be (department_id, lang_code) where lang_code is something like "en-us".

              I'm really looking for any example where the owning field of a ManyToOne relationship is also part of a composite key (via either IdClass or EmbeddedId.)





              • 4. Re: ManyToOne and Composite Keys
                jimk1723

                I think I answered my own question - I was hung up on the seam-gen'ed code; I implemented my own entities which seem to work fine.

                I removed the mappedBy attribute on the @OneToMany annotation and added a @JoinColumn annotation - that seemed to fix things.

                package com.mydomain.example;
                
                import java.util.HashSet;
                import java.util.Set;
                
                import javax.persistence.CascadeType;
                import javax.persistence.Column;
                import javax.persistence.Entity;
                import javax.persistence.FetchType;
                import javax.persistence.GeneratedValue;
                import javax.persistence.Id;
                import javax.persistence.JoinColumn;
                import javax.persistence.OneToMany;
                import javax.persistence.Table;
                
                import org.hibernate.validator.NotNull;
                
                /**
                 * Department generated by hbm2java
                 */
                @Entity
                @Table(name = "DEPARTMENT")
                public class Department implements java.io.Serializable {
                
                 private long departmentId;
                
                 private Set<DepartmentStrings> strings = new HashSet<DepartmentStrings>(0);
                
                 public Department() {
                 }
                
                 public Department(long departmentId) {
                 this.departmentId = departmentId;
                 }
                
                 public Department(long departmentId,
                 Set<DepartmentStrings> departmentStringses) {
                 this.departmentId = departmentId;
                
                 this.strings = departmentStringses;
                 }
                
                 @Id
                 @Column(name = "DEPARTMENT_ID", unique = true, nullable = false, precision = 16, scale = 0)
                 @NotNull
                 @GeneratedValue
                 public long getDepartmentId() {
                 return this.departmentId;
                 }
                
                 public void setDepartmentId(long departmentId) {
                 this.departmentId = departmentId;
                 }
                
                 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
                 @JoinColumn(name = "DEPARTMENT_ID")
                 public Set<DepartmentStrings> getStrings() {
                 return this.strings;
                 }
                
                 public void setStrings(Set<DepartmentStrings> strings) {
                 this.strings = strings;
                 }
                
                }
                



                package com.mydomain.example;
                
                import javax.persistence.AttributeOverride;
                import javax.persistence.AttributeOverrides;
                import javax.persistence.Column;
                import javax.persistence.EmbeddedId;
                import javax.persistence.Entity;
                import javax.persistence.Table;
                
                import org.hibernate.validator.NotNull;
                
                /**
                 * DepartmentStrings generated by hbm2java
                 */
                @Entity
                @Table(name = "DEPARTMENT_STRINGS")
                public class DepartmentStrings implements java.io.Serializable {
                
                 private DepartmentStringsId id;
                
                 private String name;
                
                 public DepartmentStrings() {
                 }
                
                 public DepartmentStrings(DepartmentStringsId id) {
                 this.id = id;
                 }
                
                 @Column(name = "NAME")
                 public String getName() {
                 return name;
                 }
                
                 public void setName(String name) {
                 this.name = name;
                 }
                
                 @EmbeddedId
                 @AttributeOverrides( {
                 @AttributeOverride(name = "department", column = @Column(name = "DEPARTMENT_ID", precision = 16, scale = 0)),
                 @AttributeOverride(name = "langCode", column = @Column(name = "LANG_CODE", nullable = false, length = 5)) })
                 @NotNull
                 public DepartmentStringsId getId() {
                 return this.id;
                 }
                
                 public void setId(DepartmentStringsId id) {
                 this.id = id;
                 }
                }
                



                package com.mydomain.example;
                
                import java.io.Serializable;
                
                import javax.persistence.Column;
                import javax.persistence.JoinColumn;
                import javax.persistence.ManyToOne;
                
                public class DepartmentStringsId implements Serializable {
                
                 private Department department;
                
                 private String langCode;
                
                 public DepartmentStringsId() {
                 }
                
                 public DepartmentStringsId(Department department, String langCode) {
                 super();
                 this.department = department;
                 this.langCode = langCode;
                 }
                
                 @ManyToOne
                 @JoinColumn(name = "DEPARTMENT_ID")
                 public Department getDepartment() {
                 return department;
                 }
                
                 public void setDepartment(Department department) {
                 this.department = department;
                 }
                
                 @Column(name = "LANG_CODE")
                 public String getLangCode() {
                 return langCode;
                 }
                
                 public void setLangCode(String langCode) {
                 this.langCode = langCode;
                 }
                }
                


                ...and some quick TestNG methods:

                 @Test(enabled = true)
                 public void testCreateWithString() throws Exception {
                 EntityManagerFactory emf = Persistence
                 .createEntityManagerFactory("ejbexample");
                 EntityManager em = emf.createEntityManager();
                 em.getTransaction().begin();
                
                 Department d = new Department();
                
                 DepartmentStrings ds1 = new DepartmentStrings(new DepartmentStringsId(
                 d, "en-us"));
                 ds1.setName("Test name");
                
                 DepartmentStrings ds2 = new DepartmentStrings(new DepartmentStringsId(
                 d, "es-mx"));
                 ds2.setName("Pruebe el nombre");
                
                 d.getStrings().add(ds1);
                 d.getStrings().add(ds2);
                
                 em.persist(d);
                 em.getTransaction().commit();
                
                 this.departmentId = d.getDepartmentId();
                 }
                
                 @Test(enabled = true, dependsOnMethods = "testCreateWithString")
                 public void testLookup() throws Exception {
                 EntityManagerFactory emf = Persistence
                 .createEntityManagerFactory("ejbexample");
                 EntityManager em = emf.createEntityManager();
                 Department d = em.find(Department.class, this.departmentId);
                
                 assert d.getStrings().size() == 2;
                
                 for (DepartmentStrings ds : d.getStrings()) {
                 assert ds.getName().equals("Test name")
                 || ds.getName().equals("Pruebe el nombre");
                 }
                 }