Spring JPA - 实体类的包名称中的“in”单词 - 导致 JPQL 错误

Wan*_*ker 5 java spring hibernate jpa spring-data

使用 Spring-Data 与 Hibernate 观察到的问题 - Spring 4.1.5.RELEASE、Spring-Data - 1.8.0.RELEASE、Hibernate - 4.3.8.Final

公司域名以 .in 结尾,就像在印度一样。因此,我的 Java 包以“in.something ....”开头。

使用 JPA 存储库时,如果我必须对如下方法使用自定义查询:

@Query(value = "SELECT o FROM UserEntity o, UserAttribute u where o.organization.organizationType.code in ?1 and o.status in ?2 and u.attrKey = 'SOL_ID' and u.attrValue in ?3 and u.userEntity = o") 

Page<UserEntity> findByOrganizationAndStatusAndSolId(List<String> organizationTypes, List<StatusMaster> statusList, List<String> solId, Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

应用程序启动失败,因为 JPA 查询具有类的完全限定名称,并且由于包以“in”开头,因此它认为存在验证错误。

引起原因:java.lang.IllegalArgumentException:org.hibernate.hql.internal.ast.QuerySyntaxException:期望打开,发现“。” 靠近第 1 行第 44 列 [SELECT o FROM in.something.UserEntity o, in.something.UserAttribute u where o.organization.organizationType.code in ?1 和 o.status in ?2 and u.attrKey = 'SOL_ID' and u.attrValue in ?3 和 u.userEntity = o]

Caused by: java.lang.IllegalArgumentException: Validation failed for query for method public abstract org.springframework.data.domain.Page in.something.UserRepository.findByOrganizationAndStatusAndSolId(java.util.List,java.util.List,java.util.List,org.springframework.data.domain.Pageable)!
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:97)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.<init>(SimpleJpaQuery.java:66)
    at org.springframework.data.jpa.repository.query.SimpleJpaQuery.fromQueryAnnotation(SimpleJpaQuery.java:169)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$DeclaredQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:114)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateIfNotFoundQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:160)
    at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$AbstractQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:68)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.<init>(RepositoryFactorySupport.java:290)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:158)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:162)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:44)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142)
    ... 37 more
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: expecting OPEN, found '.' near line 1, column 44 [SELECT o FROM in.something.UserEntity o, in.something.UserAttribute u where o.organization.organizationType.code in ?1 and o.status in ?2 and u.attrKey = 'SOL_ID' and u.attrValue in ?3 and u.userEntity = o]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1364)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
    at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:294)
Run Code Online (Sandbox Code Playgroud)

我尝试了多种选择,但没有运气:

  1. 使用 此处的建议在实体中使用转义表名称
  2. 使用<delimited-identifiers/>
  3. 在 @Entity(name="otherName") 中指定名称

对此的任何意见都将受到高度赞赏。

更新: 当我的包以“com.something”开头时,代码曾经工作正常。但是,我重构了代码来修复包名称,之后问题开始出现

UPDATE 2 如果查询被修改为使用,SELECT o FROM UserEntity o JOIN o.attributes u...那么错误就会消失。

更新 3 - 更新中也发现了问题

@Query(value="UPDATE WebSessionEntity o SET o.lastAccessedOn = ?2 WHERE o.authSessionToken = ?1")
public int updateLastAccessedOn(String authSessionToken, Date accessDate);
Run Code Online (Sandbox Code Playgroud)

假设 WebSessionEntity 以包名称“in.something...”启动,则应用程序不会启动。在启动过程中,我收到 Hibernate 验证错误:

2015-03-24 18:52:00,810 [main] ERROR org.hibernate.hql.internal.ast.ErrorCounter - line 1:8: unexpected token: in line 1:8: unexpected token: in    
at org.hibernate.hql.internal.antlr.HqlBaseParser.updateStatement(HqlBaseParser.java:210)
...
...
Caused by: java.lang.IllegalArgumentException: node to traverse cannot be null!     
at org.hibernate.hql.internal.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:63)  
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:272)
Run Code Online (Sandbox Code Playgroud)

Kar*_*hik 1

按照惯例,当域名干扰包的命名时,使用下划线。

链接 - https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

链接的摘录,

在某些情况下,互联网域名可能不是有效的包名称。如果域名包含连字符或其他特殊字符,如果程序包名称以数字或其他不能用作 Java 名称开头的字符开头,或者如果程序包名称包含保留的 Java 关键字,则可能会发生这种情况。例如“int”。在这种情况下,建议的约定是添加下划线。

  • 发生此问题是因为“in”是 SQL 关键字。不是因为它的域名无效 (4认同)