小编典典

JPA 2和Hibernate 3.5.1成员查询不起作用

java

我正在尝试以下JPQL,但是失败了:

Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' MEMBER OF u.roles");
List users = query.query.getResultList();

我得到以下异常:

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]

我有Spring 3.0.1.RELEASE,Hibernate 3.5.1-Final和Maven来粘合依赖项。

用户类别:

@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>();

...
}

弹簧配置:

<?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依赖项。

  <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>

我正在运行单元测试以检查配置,并且我能够运行其他JPQL查询,但我无法运行的唯一条件是IS EMPTY,MEMBER OF条件。

完整的单元测试如下:

测试整合

@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;
    }
  }
}

阅读 214

收藏
2020-11-16

共1个答案

小编典典

您的查询对我来说看起来 很好 。作为记录,这是JPA 2.0规范关于MEMBER OF操作符的内容:

4.6.13集合成员表达式

MEMBER OF在collection_member_expression中使用比较运算符的语法如下:

   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

此表达式测试指定的值是否是由集合值的路径表达式指定的集合的成员。

集合成员表达式中不支持计算为可嵌入类型的表达式。在本规范的将来版本中,可能会添加对在集合成员表达式中使用可嵌入对象的支持。

如果集合值的路径表达式指定一个空集合,则MEMBER OF表达式FALSE的值为,而NOT MEMBER OF表达式的值为
TRUE。否则,如果集合成员表达式中的collection_valued_pa​​th_expression或Entity_or_value_expression的值为NULL或未知,则集合成员表达式的值为未知。

例:

SELECT p
FROM Person p
WHERE 'Joe' MEMBER OF p.nicknames

因此,由于在您的查询中看不到任何错误,因此我已经使用EclipseLink 1测试了您的代码,以下代码段就可以了:

Query query = em.createQuery("SELECT u FROM User u WHERE 'admin' MEMBER OF u.roles");
List list = query.getResultList();

但是,使用Hibernate EntityManager
3.5.1-Final确实失败。这听起来像个错误,请随时提出有关Jira的问题

1为了以防万一,我使用了以下Maven配置文件(用于JPA提供程序):

  <profile>
    <id>eclipselink</id>
    <repositories>
      <repository>
        <id>eclipselink</id>
        <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;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>

这是我的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>

更新:
HHH-5209中报告

2020-11-16