diff --git a/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java b/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java index 01b7c89..2830c7b 100755 --- a/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java +++ b/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java @@ -213,10 +213,10 @@ public static Path findPropertyPath(String propertyPath, Path startRoot, classMetadata = metaModel.managedType(associationType); LOG.log(Level.INFO, "Create a join between {0} and {1}.", new Object[]{previousClass, classMetadata.getJavaType().getName()}); - if (root instanceof Join) { - root = root.get(mappedProperty); - } else { + if (root instanceof From) { root = ((From) root).join(mappedProperty); + } else { + root = root.get(mappedProperty); } } else { LOG.log(Level.INFO, "Create property path for type {0} property {1}.", new Object[]{classMetadata.getJavaType().getName(), mappedProperty}); diff --git a/src/test/java/com/github/tennaito/rsql/jpa/AbstractVisitorTest.java b/src/test/java/com/github/tennaito/rsql/jpa/AbstractVisitorTest.java deleted file mode 100644 index 68916db..0000000 --- a/src/test/java/com/github/tennaito/rsql/jpa/AbstractVisitorTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The MIT License - * - * Copyright 2015 Antonio Rabelo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.github.tennaito.rsql.jpa; - -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -import javax.persistence.EntityManager; - -import com.github.tennaito.rsql.jpa.entity.Teacher; -import org.junit.BeforeClass; - -import com.github.tennaito.rsql.jpa.entity.Course; -import com.github.tennaito.rsql.jpa.entity.CourseDetails; -import com.github.tennaito.rsql.jpa.entity.Department; -import com.github.tennaito.rsql.jpa.entity.Person; -import com.github.tennaito.rsql.jpa.entity.Title; - -/** - * @author AntonioRabelo - */ -public abstract class AbstractVisitorTest { - - private static boolean loaded = false; - - protected Class entityClass; - protected EntityManager entityManager; - - @BeforeClass - public static void setUpBefore() throws Exception { - if (!loaded) { - - EntityManager entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); - entityManager.getTransaction().begin(); - - Title title1 = new Title(); - title1.setId(1L); - title1.setName("Phd"); - entityManager.persist(title1); - - Title title2 = new Title(); - title2.setId(2L); - title2.setName("Consultant"); - entityManager.persist(title2); - - Set titles = new HashSet<Title>(); - titles.add(title1); - titles.add(title2); - - Person head = new Person(); - head.setId(1L); - head.setName("Some"); - head.setSurname("One"); - head.setTitles(titles); - entityManager.persist(head); - - Department department = new Department(); - department.setId(1L); - department.setName("Testing"); - department.setCode("MI-MDW"); - department.setHead(head); - entityManager.persist(department); - - Teacher teacher = new Teacher(); - teacher.setId(23L); - teacher.setSpecialtyDescription("Maths"); - entityManager.persist(teacher); - - Course c = new Course(); - c.setId(1L); - c.setCode("MI-MDW"); - c.setActive(true); - c.setCredits(10); - c.setName("Testing Course"); - c.setDepartment(department); - c.setDetails(CourseDetails.of("test")); - c.getDetails().setTeacher(teacher); - c.setStartDate( new Date()); - entityManager.persist(c); - - entityManager.getTransaction().commit(); - loaded = true; - } - } -} diff --git a/src/test/java/com/github/tennaito/rsql/jpa/EntityManagerFactoryInitializer.java b/src/test/java/com/github/tennaito/rsql/jpa/EntityManagerFactoryInitializer.java deleted file mode 100644 index 2ff0c63..0000000 --- a/src/test/java/com/github/tennaito/rsql/jpa/EntityManagerFactoryInitializer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * The MIT License - * - * Copyright 2015 Antonio Rabelo - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package com.github.tennaito.rsql.jpa; - -import javax.persistence.EntityManagerFactory; -import javax.persistence.Persistence; - -/** - * @author Antonio Rabelo - */ -public class EntityManagerFactoryInitializer { - - private static EntityManagerFactory instance; - - - public static EntityManagerFactory getEntityManagerFactory() { - if (instance != null) return instance; - instance = Persistence.createEntityManagerFactory("persistenceUnit"); - - return instance; - } -} diff --git a/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java b/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java index c61a0c5..3e4ca54 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java @@ -24,17 +24,28 @@ package com.github.tennaito.rsql.jpa; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.fail; +import com.github.tennaito.rsql.builder.BuilderTools; +import com.github.tennaito.rsql.jpa.entity.Course; +import com.github.tennaito.rsql.jpa.entity.CourseDetails; +import com.github.tennaito.rsql.jpa.entity.Department; +import com.github.tennaito.rsql.jpa.entity.ObjTags; +import com.github.tennaito.rsql.jpa.entity.Person; +import com.github.tennaito.rsql.jpa.entity.Tag; +import com.github.tennaito.rsql.jpa.entity.Teacher; +import com.github.tennaito.rsql.jpa.entity.Title; +import com.github.tennaito.rsql.misc.SimpleMapper; +import com.github.tennaito.rsql.parser.ast.ComparisonOperatorProxy; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -46,14 +57,6 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; -import org.junit.Before; -import org.junit.Test; - -import com.github.tennaito.rsql.builder.BuilderTools; -import com.github.tennaito.rsql.jpa.entity.Course; -import com.github.tennaito.rsql.misc.SimpleMapper; -import com.github.tennaito.rsql.parser.ast.ComparisonOperatorProxy; - import cz.jirutka.rsql.parser.RSQLParser; import cz.jirutka.rsql.parser.ast.AbstractNode; import cz.jirutka.rsql.parser.ast.ComparisonNode; @@ -63,17 +66,99 @@ import cz.jirutka.rsql.parser.ast.Node; import cz.jirutka.rsql.parser.ast.RSQLVisitor; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.fail; + /** * @author AntonioRabelo */ -public class JpaVisitorTest extends AbstractVisitorTest<Course> { +@RunWith(Parameterized.class) +public class JpaVisitorTest { + + @Parameterized.Parameters + public static List<EntityManager[]> data() { + final TestEntityManagerBuilder testEntityManagerBuilder = new TestEntityManagerBuilder(); + final EntityManager eclipseEntityManager = testEntityManagerBuilder.buildEntityManager("persistenceUnit-eclipse"); + initialize(eclipseEntityManager); + final EntityManager hibernateEntityManager = testEntityManagerBuilder.buildEntityManager("persistenceUnit-hibernate"); + initialize(hibernateEntityManager); + return Arrays.asList(new EntityManager[]{eclipseEntityManager}, new EntityManager[]{ hibernateEntityManager}); + } final static XorNode xorNode = new XorNode(new ArrayList<Node>()); - - @Before - public void setUp() throws Exception { - entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); + + private final EntityManager entityManager; + + private Class<Course> entityClass; + + public JpaVisitorTest(EntityManager entityManager) { + this.entityManager = entityManager; entityClass = Course.class; + } + + public static void initialize(EntityManager entityManager) { + entityManager.getTransaction().begin(); + + Title title1 = new Title(); + title1.setId(1L); + title1.setName("Phd"); + entityManager.persist(title1); + + Title title2 = new Title(); + title2.setId(2L); + title2.setName("Consultant"); + entityManager.persist(title2); + + Set<Title> titles = new HashSet<Title>(); + titles.add(title1); + titles.add(title2); + + Person head = new Person(); + head.setId(1L); + head.setName("Some"); + head.setSurname("One"); + head.setTitles(titles); + entityManager.persist(head); + + Tag tag = new Tag(); + tag.setId(1L); + tag.setTag("TestTag"); + entityManager.persist(tag); + + ObjTags tags = new ObjTags(); + tags.setId(1L); + tags.setTags(Arrays.asList(tag)); + entityManager.persist(tags); + + Department department = new Department(); + department.setId(1L); + department.setName("Testing"); + department.setCode("MI-MDW"); + department.setHead(head); + department.setTags(tags); + entityManager.persist(department); + + Teacher teacher = new Teacher(); + teacher.setId(23L); + teacher.setSpecialtyDescription("Maths"); + entityManager.persist(teacher); + + Course c = new Course(); + c.setId(1L); + c.setCode("MI-MDW"); + c.setActive(true); + c.setCredits(10); + c.setName("Testing Course"); + c.setDepartment(department); + c.setDetails(CourseDetails.of("test")); + c.getDetails().setTeacher(teacher); + c.setStartDate(new Date()); + entityManager.persist(c); + + entityManager.getTransaction().commit(); } @Test @@ -671,4 +756,14 @@ public void testSelectionUsingEmbeddedAssociationField() throws Exception { List<Course> courses = entityManager.createQuery(query).getResultList(); assertEquals("Testing Course", courses.get(0).getName()); } + + @Test + public void testNestedSelection() throws Exception { + Node rootNode = new RSQLParser().parse("tags.tags.tag=in=(TestTag)"); + RSQLVisitor<CriteriaQuery<Department>, EntityManager> visitor = new JpaCriteriaQueryVisitor<Department>(); + CriteriaQuery<Department> query = rootNode.accept(visitor, entityManager); + + List<Department> departments = entityManager.createQuery(query).getResultList(); + assertEquals("Testing", departments.get(0).getName()); + } } diff --git a/src/test/java/com/github/tennaito/rsql/jpa/TestEntityManagerBuilder.java b/src/test/java/com/github/tennaito/rsql/jpa/TestEntityManagerBuilder.java new file mode 100644 index 0000000..318407b --- /dev/null +++ b/src/test/java/com/github/tennaito/rsql/jpa/TestEntityManagerBuilder.java @@ -0,0 +1,17 @@ +package com.github.tennaito.rsql.jpa; + +import javax.persistence.EntityManager; +import javax.persistence.Persistence; + +/** + * Created by ivelin on 8/15/17. + */ +public class TestEntityManagerBuilder { + + public EntityManager buildEntityManager(String persistenceUnit) { + final EntityManager entityManager = Persistence.createEntityManagerFactory(persistenceUnit).createEntityManager(); + return entityManager; + } + + +} diff --git a/src/test/java/com/github/tennaito/rsql/jpa/entity/Department.java b/src/test/java/com/github/tennaito/rsql/jpa/entity/Department.java index bd64784..4bd2c5f 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/entity/Department.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/entity/Department.java @@ -27,6 +27,7 @@ import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; /** * @@ -42,6 +43,8 @@ public class Department extends AbstractTestEntity { @ManyToOne private Person head; + @OneToOne + private ObjTags tags; public String getCode() { return code; @@ -59,4 +62,11 @@ public void setHead(Person head) { this.head = head; } + public ObjTags getTags() { + return tags; + } + + public void setTags(ObjTags tags) { + this.tags = tags; + } } diff --git a/src/test/java/com/github/tennaito/rsql/jpa/entity/ObjTags.java b/src/test/java/com/github/tennaito/rsql/jpa/entity/ObjTags.java new file mode 100644 index 0000000..28891f7 --- /dev/null +++ b/src/test/java/com/github/tennaito/rsql/jpa/entity/ObjTags.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) Axway Software, 2017. All Rights Reserved. + * + */ + +package com.github.tennaito.rsql.jpa.entity; + +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.OneToMany; + + +@Entity +public class ObjTags extends AbstractTestEntity{ + + @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) + private List<Tag> tags; + + public List<Tag> getTags() { + return tags; + } + + public void setTags(List<Tag> tags) { + this.tags = tags; + } +} diff --git a/src/test/java/com/github/tennaito/rsql/jpa/entity/Tag.java b/src/test/java/com/github/tennaito/rsql/jpa/entity/Tag.java new file mode 100644 index 0000000..eb79db6 --- /dev/null +++ b/src/test/java/com/github/tennaito/rsql/jpa/entity/Tag.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) Axway Software, 2017. All Rights Reserved. + * + */ + +package com.github.tennaito.rsql.jpa.entity; + +import javax.persistence.Column; +import javax.persistence.Entity; + +/** + * Created by ivelin on 2/24/17. + */ +@Entity +public class Tag extends AbstractTestEntity { + + @Column(name = "TAG", nullable = false) + private String tag; + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } +} diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index 215c469..9dfdd4b 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -4,8 +4,11 @@ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> - <persistence-unit name="persistenceUnit"> + + <persistence-unit name="persistenceUnit-eclipse"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> + <class>com.github.tennaito.rsql.jpa.entity.Tag</class> + <class>com.github.tennaito.rsql.jpa.entity.ObjTags</class> <class>com.github.tennaito.rsql.jpa.entity.Course</class> <class>com.github.tennaito.rsql.jpa.entity.Department</class> <class>com.github.tennaito.rsql.jpa.entity.Person</class> @@ -13,7 +16,7 @@ <class>com.github.tennaito.rsql.jpa.entity.Teacher</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> - <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:ProductDAOTest" /> + <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:EclipseProductDAOTest" /> <property name="javax.persistence.jdbc.user" value="sa" /> <property name="eclipselink.logging.level" value="FINE" /> <property name="eclipselink.target-database" value="HSQL" /> @@ -24,23 +27,24 @@ <property name="eclipselink.logging.parameters" value="true" /> </properties> </persistence-unit> - - <!-- - <persistence-unit name="persistenceUnit"> - <provider>org.hibernate.ejb.HibernatePersistence</provider> - <class>com.github.tennaito.rsql.jpa.entity.Course</class> - <class>com.github.tennaito.rsql.jpa.entity.Department</class> - <class>com.github.tennaito.rsql.jpa.entity.Person</class> - <class>com.github.tennaito.rsql.jpa.entity.Title</class> - <properties> - <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> - <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:ProductDAOTest" /> - <property name="javax.persistence.jdbc.user" value="sa" /> - <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> - <property name="hibernate.hbm2ddl.auto" value="create-drop" /> - <property name="hibernate.show_sql" value="true" /> - <property name="hibernate.format_sql" value="true" /> - </properties> - </persistence-unit> - --> + + <persistence-unit name="persistenceUnit-hibernate"> + <provider>org.hibernate.ejb.HibernatePersistence</provider> + <class>com.github.tennaito.rsql.jpa.entity.Tag</class> + <class>com.github.tennaito.rsql.jpa.entity.ObjTags</class> + <class>com.github.tennaito.rsql.jpa.entity.Course</class> + <class>com.github.tennaito.rsql.jpa.entity.Department</class> + <class>com.github.tennaito.rsql.jpa.entity.Person</class> + <class>com.github.tennaito.rsql.jpa.entity.Title</class> + <properties> + <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> + <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:HibernateProductDAOTest" /> + <property name="javax.persistence.jdbc.user" value="sa" /> + <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> + <property name="hibernate.hbm2ddl.auto" value="create-drop" /> + <property name="hibernate.show_sql" value="true" /> + <property name="hibernate.format_sql" value="true" /> + </properties> + </persistence-unit> + </persistence>