/* * Hibernate, Relational Persistence for Idiomatic Java * * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.jpa.test.criteria.components; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Embeddable; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.MappedSuperclass; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.junit.Before; import org.junit.Test; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.transaction.TransactionUtil; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; /** * @author Andrea Boriero */ @TestForIssue(jiraKey = "HHH-6562") public class EntitySuperclassComponentWithCollectionTest extends BaseEntityManagerFunctionalTestCase { private Projects projects; @Override protected Class<?>[] getAnnotatedClasses() { return new Class[] {Employee.class, Manager.class, Project.class, Person.class, Leader.class}; } @Before public void setUp() throws Exception { TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { projects = new Projects(); projects.addPreviousProject( new Project( "First" ) ); projects.addPreviousProject( new Project( "Second" ) ); projects.setCurrentProject( new Project( "Third" ) ); ContactDetail contactDetail = new ContactDetail(); contactDetail.setEmail( "abc@mail.org" ); contactDetail.addPhone( new Phone( "+4411111111" ) ); final Manager manager = new Manager(); manager.setProjects( projects ); manager.setContactDetail( contactDetail ); entityManager.persist( manager ); final Leader leader = new Leader(); leader.setInformation( new Information() ); ContactDetail infoContactDetail = new ContactDetail(); infoContactDetail.setEmail( "xyz@mail.org" ); infoContactDetail.addPhone( new Phone( "999-999-9999" ) ); leader.getInformation().setInfoContactDetail( infoContactDetail ); entityManager.persist( leader ); } ); } @Test public void testSizeExpressionForTheOneToManyPropertyOfAComponent() { TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Manager> query = builder.createQuery( Manager.class ); Root<Manager> root = query.from( Manager.class ); query.where( builder.equal( builder.size( root.get( "projects" ).get( "previousProjects" ) ) , 2 ) ); final List<Manager> results = entityManager.createQuery( query ).getResultList(); assertThat( results.size(), is( 1 ) ); } ); } @Test public void testSizeExpressionForTheElementCollectionPropertyOfAComponent() { TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Manager> query = builder.createQuery( Manager.class ); Root<Manager> root = query.from( Manager.class ); query.where( builder.equal( builder.size( root.get( "contactDetail" ).get( "phones" ) ) , 1 ) ); final List<Manager> results = entityManager.createQuery( query ).getResultList(); assertThat( results.size(), is( 1 ) ); } ); } @Test public void testSizeExpressionForTheElementCollectionPropertyOfASubComponent() { TransactionUtil.doInJPA( this::entityManagerFactory, entityManager -> { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Leader> query = builder.createQuery( Leader.class ); Root<Leader> root = query.from( Leader.class ); query.where( builder.equal( builder.size( root.get( "information" ).get( "infoContactDetail" ).get( "phones" ) ) , 1 ) ); final List<Leader> results = entityManager.createQuery( query ).getResultList(); assertThat( results.size(), is( 1 ) ); } ); } @MappedSuperclass public static abstract class AbstractEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) protected Long id; public Long getId() { return id; } } @Entity(name = "Employee") @Table(name = "EMPLOYEE") public static class Employee extends AbstractEntity { @Embedded private Projects projects; @Embedded private ContactDetail contactDetail; public void setProjects(Projects projects) { this.projects = projects; } public void setContactDetail(ContactDetail contactDetail) { this.contactDetail = contactDetail; } } @Entity(name = "Manager") @Table(name = "MANAGER") public static class Manager extends Employee { } @Embeddable public static class ContactDetail { private String email; @ElementCollection private List<Phone> phones = new ArrayList<>(); public void addPhone(Phone phone) { this.phones.add( phone ); } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } @Embeddable public static class Projects { @OneToMany(cascade = CascadeType.PERSIST) private Set<Project> previousProjects = new HashSet<>(); @ManyToOne(cascade = CascadeType.PERSIST) private Project currentProject; public void setCurrentProject(Project project) { this.currentProject = project; } public void addPreviousProject(Project project) { this.previousProjects.add( project ); } public Set<Project> getPreviousProjects() { return previousProjects; } public Project getCurrentProject() { return currentProject; } } @Entity(name = "Project") @Table(name = "PROJECT") public static class Project extends AbstractEntity { public Project() { } public Project(String name) { this.name = name; } private String name; public void setName(String name) { this.name = name; } public String getName() { return this.name; } } @Embeddable public static class Phone { @Column(name = "phone_number") private String number; public Phone() { } public Phone(String number) { this.number = number; } public String getNumber() { return this.number; } } @Entity(name = "Person") @Table(name="PERSON") public static class Person extends AbstractEntity { @Embedded private Information information; public Information getInformation() { return information; } public void setInformation(Information information) { this.information = information; } } @Entity(name="Leader") @Table(name="LEADER") public static class Leader extends Person { } @Embeddable public static class Information { @Embedded private ContactDetail infoContactDetail; public ContactDetail getInfoContactDetail() { return infoContactDetail; } public void setInfoContactDetail(ContactDetail infoContactDetail) { this.infoContactDetail = infoContactDetail; } } }