diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ContactInfo.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ContactInfo.java new file mode 100644 index 0000000000..ac0625ec66 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ContactInfo.java @@ -0,0 +1,24 @@ +package org.hibernate.test.annotations.manytomany; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ManyToMany; +import java.util.List; + +@Embeddable +public class ContactInfo { +// @ManyToOne +// Address address; // Unidirectional + + List phoneNumbers; // Bidirectional + + @ManyToMany(cascade= CascadeType.ALL) + public List getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(List phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } + +} diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/Employee.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/Employee.java index d5058d94f7..7cb5d3c7f9 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/Employee.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/Employee.java @@ -4,6 +4,7 @@ package org.hibernate.test.annotations.manytomany; import java.io.Serializable; import java.util.Collection; import javax.persistence.CascadeType; +import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @@ -26,6 +27,29 @@ public class Employee implements Serializable { private Integer id; private Collection employers; private String name; + ContactInfo contactInfo; + JobInfo jobInfo; + + // ContactInfo is for ManyToMany testing + @Embedded + public ContactInfo getContactInfo() { + return contactInfo; + } + + public void setContactInfo(ContactInfo contactInfo) { + this.contactInfo = contactInfo; + } + + // JobInfo is for OneToMany testing + @Embedded + public JobInfo getJobInfo() { + return jobInfo; + } + + public void setJobInfo(JobInfo jobInfo) { + this.jobInfo = jobInfo; + } + @Column(name="fld_name") public String getName() { diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/JobInfo.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/JobInfo.java new file mode 100644 index 0000000000..b92d23691d --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/JobInfo.java @@ -0,0 +1,29 @@ +package org.hibernate.test.annotations.manytomany; + +import javax.persistence.CascadeType; +import javax.persistence.Embeddable; +import javax.persistence.ManyToOne; + +@Embeddable +public class JobInfo { + String jobDescription; + ProgramManager pm; // Bidirectional + + public String getJobDescription() { + return jobDescription; + } + + public void setJobDescription( String jobDescription ) { + this.jobDescription = jobDescription; + } + + @ManyToOne( cascade= CascadeType.ALL) + public ProgramManager getPm() { + return pm; + } + + public void setPm( ProgramManager pm ) { + this.pm = pm; + } + +} diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java index 61815708ed..7e60085e2c 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ManyToManyTest.java @@ -1,4 +1,5 @@ //$Id$ +//$Id$ package org.hibernate.test.annotations.manytomany; @@ -7,6 +8,7 @@ import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; import org.hibernate.Hibernate; @@ -641,6 +643,81 @@ public class ManyToManyTest extends TestCase { s.close(); } + // Test for HHH-4685 + // Section 11.1.25 + // The ManyToMany annotation may be used within an embeddable class contained within an entity class to specify a + // relationship to a collection of entities[101]. If the relationship is bidirectional and the entity containing + // the embeddable class is the owner of the relationship, the non-owning side must use the mappedBy element of the + // ManyToMany annotation to specify the relationship field or property of the embeddable class. The dot (".") + // notation syntax must be used in the mappedBy element to indicate the relationship attribute within the embedded + // attribute. The value of each identifier used with the dot notation is the name of the respective embedded field + // or property. + public void testManyToManyEmbeddableBiDirectionalDotNotationInMappedBy() throws Exception { + Session s; + Transaction tx; + s = openSession(); + tx = s.beginTransaction(); + Employee e = new Employee(); + e.setName( "Sharon" ); + List phoneNumbers = new ArrayList(); + Collection employees = new ArrayList(); + employees.add( e ); + ContactInfo contactInfo = new ContactInfo(); + PhoneNumber number = new PhoneNumber(); + number.setEmployees( employees ); + phoneNumbers.add( number ); + contactInfo.setPhoneNumbers( phoneNumbers ); + e.setContactInfo( contactInfo ); + s.persist( e ); + s.flush(); + s.clear(); + tx.commit(); + + tx.begin(); + e = (Employee)s.get( e.getClass(),e.getId() ); + // follow both directions of many to many association + assertEquals("same employee", e.getName(), e.getContactInfo().getPhoneNumbers().get(0).getEmployees().iterator().next().getName()); + tx.commit(); + + s.close(); + } + + // Test for HHH-4685 + // Section 11.1.26 + // The ManyToOne annotation may be used within an embeddable class to specify a relationship from the embeddable + // class to an entity class. If the relationship is bidirectional, the non-owning OneToMany entity side must use the + // mappedBy element of the OneToMany annotation to specify the relationship field or property of the embeddable field + // or property on the owning side of the relationship. The dot (".") notation syntax must be used in the mappedBy + // element to indicate the relationship attribute within the embedded attribute. The value of each identifier used + // with the dot notation is the name of the respective embedded field or property. + public void testOneToManyEmbeddableBiDirectionalDotNotationInMappedBy() throws Exception { + Session s; + Transaction tx; + s = openSession(); + tx = s.beginTransaction(); + Employee e = new Employee(); + JobInfo job = new JobInfo(); + job.setJobDescription( "Sushi Chef" ); + ProgramManager pm = new ProgramManager(); + Collection employees = new ArrayList(); + employees.add(e); + pm.setManages( employees ); + job.setPm(pm); + e.setJobInfo( job ); + s.persist( e ); + s.flush(); + s.clear(); + tx.commit(); + + tx.begin(); + e = (Employee) s.get( e.getClass(), e.getId() ); + assertEquals( "same job in both directions", + e.getJobInfo().getJobDescription(), + e.getJobInfo().getPm().getManages().iterator().next().getJobInfo().getJobDescription() ); + tx.commit(); + s.close(); + } + /** * @see org.hibernate.test.annotations.TestCase#getMappings() */ @@ -664,7 +741,9 @@ public class ManyToManyTest extends TestCase { Inspector.class, InspectorPrefixes.class, BuildingCompany.class, - Building.class + Building.class, + PhoneNumber.class, + ProgramManager.class }; } diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/PhoneNumber.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/PhoneNumber.java new file mode 100644 index 0000000000..49cdf7b87e --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/PhoneNumber.java @@ -0,0 +1,31 @@ +package org.hibernate.test.annotations.manytomany; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import java.util.Collection; + +@Entity +public class PhoneNumber { + int phNumber; + Collection employees; + + @Id + public int getPhNumber() { + return phNumber; + } + + public void setPhNumber(int phNumber) { + this.phNumber = phNumber; + } + + @ManyToMany(mappedBy="contactInfo.phoneNumbers", cascade= CascadeType.ALL) + public Collection getEmployees() { + return employees; + } + + public void setEmployees(Collection employees) { + this.employees = employees; + } +} diff --git a/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ProgramManager.java b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ProgramManager.java new file mode 100644 index 0000000000..49f9102d19 --- /dev/null +++ b/annotations/src/test/java/org/hibernate/test/annotations/manytomany/ProgramManager.java @@ -0,0 +1,33 @@ +package org.hibernate.test.annotations.manytomany; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.Collection; + +@Entity +public class ProgramManager { + int id; + + Collection manages; + + @Id + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @OneToMany( mappedBy="jobInfo.pm", cascade= CascadeType.ALL ) + public Collection getManages() { + return manages; + } + + public void setManages( Collection manages ) { + this.manages = manages; + } + +}