I'm trying the following JPQL and it fails misserably:
Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' MEMBER OF u.roles");
List users = query.query.getResultList();
I get the following exception:
ERROR [main] PARSER.error(454) | <AST>:0:0: unexpected end of subtree
java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException: unexpected end of subtree [SELECT u FROM com.online.data.User u WHERE 'admin' MEMBER OF u.roles] ERROR [main] PARSER.error(454) | <AST>:0:0: expecting "from", found '<ASTNULL>'
...
...
Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected end of subtree [SELECT u FROM com.online.data.User u WHERE 'admin' MEMBER OF u.roles]
I have Spring 3.0.1.RELEASE, Hibernate 3.5.1-Final and maven to glue dependencies.
User class:
@Entity
public class User {
@Id
@Column(name = "USER_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(unique = true, nullable = false)
private String username;
private boolean enabled;
@ElementCollection
private Set<String> roles = new HashSet<String>();
...
}
Spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/tx/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- Reading annotation driven configuration -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="100" />
<property name="maxWait" value="1000" />
<property name="poolPreparedStatements" value="true" />
<property name="defaultAutoCommit" value="true" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="${hibernate.dialect}" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.show_comments">true</prop>
</props>
</property>
<property name="persistenceUnitName" value="punit" />
</bean>
<bean id="JpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
Persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="punit" transaction-type="RESOURCE_LOCAL" />
</persistence>
pom.xml maven dependencies.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernate.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-acl</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
<properties>
<!-- Application settings -->
<spring.version>3.0.1.RELEASE</spring.version>
<hibernate.version>3.5.1-Final</hibernate.version>
Im running a unit test to check the configuration and I am able to run other JPQL queries the only ones that I am unable to run are the IS EMPTY, MEMBER OF conditions.
The complete unit test is as follows:
TestIntegration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring/dataLayer.xml"})
@Transactional
@TransactionConfiguration
public class TestUserDaoImplIntegration {
@PersistenceContext
private EntityManager em;
@Test
public void shouldTest() throws Exception {
try {
//WORKS
Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' in elements(u.roles)");
List users = query.query.getResultList();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
try {
//DOES NOT WORK
Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' MEMBER OF u.roles");
List users = query.query.getResultList();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
Your query looks perfectly fine to me. For the record, this is what the JPA 2.0 specification writes about the MEMBER OF
operator:
4.6.13 Collection Member Expressions
The syntax for the use of the comparison operator
MEMBER OF
in an collection_member_expression is as follows:collection_member_expression ::= entity_or_value_expression [NOT] MEMBER [OF] collection_valued_path_expression entity_or_value_expression ::= single_valued_object_path_expression | state_field_path_expression | simple_entity_or_value_expression simple_entity_or_value_expression ::= identification_variable | input_parameter | literal
This expression tests whether the designated value is a member of the collection specified by the collection-valued path expression.
Expressions that evaluate to embeddable types are not supported in collection member expressions. Support for use of embeddables in collection member expressions may be added in a future release of this specification.
If the collection valued path expression designates an empty collection, the value of the
MEMBER
OF expression isFALSE
and the value of theNOT MEMBER OF
expression isTRUE
. Otherwise, if the value of the collection_valued_path_expression or entity_or_value_expression in the collection member expression is NULL or unknown, the value of the collection member expression is unknown.Example:
SELECT p FROM Person p WHERE 'Joe' MEMBER OF p.nicknames
So, because I can't see anything wrong in your query, I've tested your code with EclipseLink1 and the following snippet just works:
Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' MEMBER OF u.roles");
List list = query.getResultList();
But fails indeed with Hibernate EntityManager 3.5.1-Final. This sounds like a bug, feel free to raise a Jira issue.
1 Just in case, I used the following Maven profile (for the JPA provider):
<profile>
<id>eclipselink</id>
<repositories>
<repository>
<id>eclipselink</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo/</url>
</repository>
</repositories>
<dependencies>
<!-- See http://wiki.eclipse.org/EclipseLink/Maven -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.0</version>
</dependency>
<!-- optional - only needed if you are using JPA outside of a Java EE container-->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
And this is my persistence.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="TestPu" transaction-type="RESOURCE_LOCAL">
<class>com.stackoverflow.q2688144.User</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:testdb;create=true"/>
<property name="eclipselink.target-database" value="DERBY"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
Update: reported in HHH-5209
Hibernate Bug #HHH-5209, as workaround use the following syntax:
select user from User user where :role in elements(user.roles)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With