diff --git a/pom.xml b/pom.xml index 4769ffd..f0e743e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,11 +6,11 @@ rsql-jpa 2.0.3-SNAPSHOT jar - + RSQL-JPA 2015 - A application used to translate RSQL nodes to JPA Criteria Query. + A application used to translate RSQL nodes to JPA Criteria Query. http://github.com/tennaito/rsql-jpa @@ -20,26 +20,28 @@ http://opensource.org/licenses/MIT - + - - Antonio Rabelo - - - - + + Antonio Rabelo + + + + https://github.com/tennaito/rsql-jpa/ scm:git:https://github.com/tennaito/rsql-jpa.git scm:git:https://github.com/tennaito/rsql-jpa.git - HEAD - + HEAD + UTF-8 + 1.8 + 1.8 @@ -49,30 +51,30 @@ cz.jirutka.rsql rsql-parser - 2.0.0 + 2.1.0 - - - org.eclipse.persistence - javax.persistence - 2.1.0 - + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + 1.0.0.Final + - - org.hibernate - hibernate-entitymanager - 4.3.10.Final - test - + + org.hibernate + hibernate-entitymanager + 5.2.15.Final + test + - - org.eclipse.persistence - eclipselink - 2.6.0-M3 - test - + + org.eclipse.persistence + eclipselink + 2.7.4 + test + junit junit @@ -83,7 +85,7 @@ org.hsqldb hsqldb - 1.8.0.10 + 2.4.1 test @@ -92,73 +94,73 @@ - release - - - - org.apache.maven.plugins - maven-release-plugin - 2.5 - - true - false - release - deploy nexus-staging:release - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.3 - true - - ossrh - https://oss.sonatype.org/ - false - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - + release + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + true + false + release + deploy nexus-staging:release + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.3 + true + + ossrh + https://oss.sonatype.org/ + false + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.0 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + @@ -225,7 +227,7 @@ org.jacoco jacoco-maven-plugin - 0.7.1.201405082137 + 0.8.3 @@ -257,30 +259,58 @@ org.eluder.coveralls coveralls-maven-plugin - 2.2.0 + 2.2.0 - + - + + + + maven-compiler-plugin + 3.8.0 + + + + + + + default-compile + compile + + compile + + + + default-testCompile + test-compile + + testCompile + + + + + + + - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - - travis - https://travis-ci.org/tennaito/rsql-jpa - - - GitHub - https://github.com/tennaito/rsql-jpa/issues - + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + travis + https://travis-ci.org/tennaito/rsql-jpa + + + GitHub + https://github.com/tennaito/rsql-jpa/issues + 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..7c44f39 100755 --- a/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java +++ b/src/main/java/com/github/tennaito/rsql/jpa/PredicateBuilder.java @@ -207,11 +207,25 @@ public static Path findPropertyPath(String propertyPath, Path startRoot, throw new IllegalArgumentException("Unknown property: " + mappedProperty + " from entity " + classMetadata.getJavaType().getName()); } - if (isAssociationType(mappedProperty, classMetadata)) { + //Add Support of ElementCollection which was forgotten in hibernate version 5.2.15.Final + /** + * see org.hibernate.metamodel.internal.isAssociation() + * public boolean isAssociation() { + * return this.getPersistentAttributeType() == PersistentAttributeType.MANY_TO_ONE || this.getPersistentAttributeType() == PersistentAttributeType.ONE_TO_ONE; + * } + */ + if (isAssociationType(mappedProperty, classMetadata) || + classMetadata.getAttribute(mappedProperty).getPersistentAttributeType() == PersistentAttributeType.ELEMENT_COLLECTION){ + Class associationType = findPropertyType(mappedProperty, classMetadata); String previousClass = classMetadata.getJavaType().getName(); - classMetadata = metaModel.managedType(associationType); - LOG.log(Level.INFO, "Create a join between {0} and {1}.", new Object[]{previousClass, classMetadata.getJavaType().getName()}); + + if (isAssociationType(mappedProperty, classMetadata)) { + classMetadata = metaModel.managedType(associationType); + LOG.log(Level.INFO, "Create a join between {0} and {1}.", new Object[]{previousClass, classMetadata.getJavaType().getName()}); + } else { + LOG.log(Level.INFO, "Create a join between {0} and {1}.", new Object[]{previousClass, mappedProperty}); + } if (root instanceof Join) { root = root.get(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 index 68916db..79b9f8f 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/AbstractVisitorTest.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/AbstractVisitorTest.java @@ -23,21 +23,16 @@ */ package com.github.tennaito.rsql.jpa; +import java.util.Arrays; 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 com.github.tennaito.rsql.jpa.entity.*; 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 */ @@ -45,11 +40,11 @@ public abstract class AbstractVisitorTest { private static boolean loaded = false; - protected Class entityClass; - protected EntityManager entityManager; + Class entityClass; + EntityManager entityManager; @BeforeClass - public static void setUpBefore() throws Exception { + public static void setUpBefore() { if (!loaded) { EntityManager entityManager = EntityManagerFactoryInitializer.getEntityManagerFactory().createEntityManager(); @@ -75,6 +70,20 @@ public static void setUpBefore() throws Exception { head.setSurname("One"); head.setTitles(titles); entityManager.persist(head); + + Person student1 = new Person(); + student1.setId(2L); + student1.setName("Manfred"); + student1.setSurname("Bayo"); + student1.setTitles(titles); + entityManager.persist(student1); + + Person student2 = new Person(); + student2.setId(3L); + student2.setName("Bob"); + student2.setSurname("Dilan"); + student2.setTitles(titles); + entityManager.persist(student2); Department department = new Department(); department.setId(1L); @@ -83,11 +92,23 @@ public static void setUpBefore() throws Exception { department.setHead(head); entityManager.persist(department); + Department department2 = new Department(); + department2.setId(2L); + department2.setName("Testing2"); + department2.setCode("DE-MDW"); + department2.setHead(head); + entityManager.persist(department2); + Teacher teacher = new Teacher(); teacher.setId(23L); teacher.setSpecialtyDescription("Maths"); entityManager.persist(teacher); - + + Teacher teacher2 = new Teacher(); + teacher2.setId(24L); + teacher2.setSpecialtyDescription("Physics"); + entityManager.persist(teacher2); + Course c = new Course(); c.setId(1L); c.setCode("MI-MDW"); @@ -99,6 +120,36 @@ public static void setUpBefore() throws Exception { c.getDetails().setTeacher(teacher); c.setStartDate( new Date()); entityManager.persist(c); + + Course c2 = new Course(); + c2.setId(2L); + c2.setCode("BI-MDW"); + c2.setActive(true); + c2.setCredits(10); + c2.setName("Testing Physics"); + c2.setDepartment(department2); + c2.setDetails(CourseDetails.of("test")); + c2.getDetails().setTeacher(teacher2); + c2.setStartDate( new Date()); + entityManager.persist(c2); + + PersonCourse personCourse = new PersonCourse(); + personCourse.setId(1L); + personCourse.setCode(c.getCode()); + personCourse.setPersonId(student1.getId()); + entityManager.persist(personCourse); + + PersonCourse personCourse2 = new PersonCourse(); + personCourse2.setId(2L); + personCourse2.setCode(c2.getCode()); + personCourse2.setPersonId(student1.getId()); + entityManager.persist(personCourse2); + + PersonCourse personCourse3 = new PersonCourse(); + personCourse3.setId(3L); + personCourse3.setCode(c2.getCode()); + personCourse3.setPersonId(student2.getId()); + entityManager.persist(personCourse3); entityManager.getTransaction().commit(); loaded = true; 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..080a0ad 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/JpaVisitorTest.java @@ -46,6 +46,7 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import com.github.tennaito.rsql.jpa.entity.Person; import org.junit.Before; import org.junit.Test; @@ -119,7 +120,7 @@ public void testNotEqualSelection() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + assertEquals(1, courses.size()); } @Test @@ -129,7 +130,7 @@ public void testGreaterThanSelection() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + assertEquals(1, courses.size()); } @Test @@ -139,7 +140,7 @@ public void testGreaterThanDate() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); + assertEquals(2, courses.size()); } @Test @@ -149,7 +150,7 @@ public void testGreaterThanString() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); + assertEquals(2, courses.size()); } @Test @@ -194,6 +195,29 @@ public void testGreaterThanEqualSelectionForString() throws Exception { assertEquals("Testing Course", courses.get(0).getName()); } + @Test + public void testEqualSelectionForStringInElementCollection() { + Node rootNode = new RSQLParser().parse("courses=='MI-MDW'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(1, courses.size()); + } + + + @Test + public void testEqualSelectionForStringInElementCollectionFailed() { + Node rootNode = new RSQLParser().parse("courses=='DE-MDW'"); + RSQLVisitor, EntityManager> visitor = new JpaCriteriaQueryVisitor(); + CriteriaQuery query = rootNode.accept(visitor, entityManager); + + List courses = entityManager.createQuery(query).getResultList(); + assertEquals(0, courses.size()); + } + + + @Test public void testGreaterThanEqualNotComparable() throws Exception { try { @@ -233,7 +257,7 @@ public void testLessThanDate() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); + assertEquals(2, courses.size()); } @Test @@ -243,7 +267,7 @@ public void testLessThanString() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(1, courses.size()); + assertEquals(2, courses.size()); } @Test @@ -328,7 +352,7 @@ public void testNotLikeSelection() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); List courses = entityManager.createQuery(query).getResultList(); - assertEquals(0, courses.size()); + assertEquals(1, courses.size()); } @@ -503,7 +527,7 @@ public void testOrSelectionCount() throws Exception { CriteriaQuery query = rootNode.accept(visitor, entityManager); Long courseCount = entityManager.createQuery(query).getSingleResult(); - assertEquals((Long)1l, courseCount); + assertEquals((Long) 2L, courseCount); } @Test @@ -572,7 +596,7 @@ public void testPrivateConstructor() throws Exception { // When used it returns a instance? assertNotNull(predicateBuilder); } - + ////////////////////////// Mocks ////////////////////////// protected static class OtherNode extends AbstractNode { diff --git a/src/test/java/com/github/tennaito/rsql/jpa/entity/Person.java b/src/test/java/com/github/tennaito/rsql/jpa/entity/Person.java index 5284f62..19d78c4 100644 --- a/src/test/java/com/github/tennaito/rsql/jpa/entity/Person.java +++ b/src/test/java/com/github/tennaito/rsql/jpa/entity/Person.java @@ -24,12 +24,11 @@ */ package com.github.tennaito.rsql.jpa.entity; +import java.util.ArrayList; +import java.util.List; import java.util.Set; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.ManyToMany; +import javax.persistence.*; /** * @@ -44,7 +43,12 @@ public class Person extends AbstractTestEntity { @ManyToMany(cascade=CascadeType.PERSIST) private Set titles; - + + @ElementCollection(targetClass = String.class) + @CollectionTable(name = "PersonCourse", joinColumns = @JoinColumn(name = "personId")) + @Column(name = "code") + private List<String> courses = new ArrayList<String>(); + public String getSurname() { return surname; } diff --git a/src/test/java/com/github/tennaito/rsql/jpa/entity/PersonCourse.java b/src/test/java/com/github/tennaito/rsql/jpa/entity/PersonCourse.java new file mode 100644 index 0000000..a50a7e2 --- /dev/null +++ b/src/test/java/com/github/tennaito/rsql/jpa/entity/PersonCourse.java @@ -0,0 +1,61 @@ +/* + * The MIT License + * + * Copyright 2013 Jakub Jirutka <jakub@jirutka.cz>. + * 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.entity; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import java.util.Set; + +/** + * + * @author Merlin Fotsing + */ +@Entity +public class PersonCourse extends AbstractTestEntity { + + @Column + private Long personId; + + @Column + private String code; + + public Long getPersonId() { + return personId; + } + + public void setPersonId(Long personId) { + this.personId = personId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } +} diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml index 215c469..1f0f4b0 100644 --- a/src/test/resources/META-INF/persistence.xml +++ b/src/test/resources/META-INF/persistence.xml @@ -11,6 +11,7 @@ <class>com.github.tennaito.rsql.jpa.entity.Person</class> <class>com.github.tennaito.rsql.jpa.entity.Title</class> <class>com.github.tennaito.rsql.jpa.entity.Teacher</class> + <class>com.github.tennaito.rsql.jpa.entity.PersonCourse</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:ProductDAOTest" />