繁体   English   中英

谁能说出为什么此JPA条件查询在执行时(休眠)会生成无效的SQL语句,以及如何解决它?

[英]Can anyone tell why this JPA criteria query generates an invalid SQL statement when executed (Hibernate) and how to fix it?

我很难构造一个条件查询来从id = 2的Role实体获取“ permissions”属性。permission属性为Set类型,因此我正在创建一个联接并从中选择,但是查询失败,语法无效,报告“'where子句'中的未知列'2L'”

生成错误的条件查询是通过以下方式构建的:

EntityManager entityManager = getEntityManager();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();

Class<?> queryScopeClass = temp.pack.commons.user.Role.class;

Root<?> from = criteriaQuery.from(queryScopeClass);

Path<?> idAttrPath = from.get("id");
// also tried criteriaBuilder.equal(attributePath, new Long(2))
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal(new Long(2)))
criteriaQuery.where(predicate);


Path<?> attributePath = from.get("permissions");
PluralAttributePath<?> pluralAttrPath = (PluralAttributePath<?>)attributePath;
PluralAttribute<?, ?, ?> pluralAttr = pluralAttrPath.getAttribute();


Join<?, ?> join = from.join((SetAttribute<Object,?>)pluralAttr);

TypedQuery<Object> typedQuery = entityManager.createQuery(criteriaQuery.select(join));
return (List<P>)typedQuery.getResultList();

当我执行该行以实际返回结果时,将引发以下异常:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:250)
    at org.hibernate.ejb.criteria.CriteriaQueryCompiler$3.getResultList(CriteriaQueryCompiler.java:260)
    at temp.pack.dao.impl.DefaultDAOService.getProperties(DefaultDAOService.java:628)
...
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
    at org.hibernate.loader.Loader.doList(Loader.java:2452)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
    at org.hibernate.loader.Loader.list(Loader.java:2187)
    at org.hibernate.hql.classic.QueryTranslatorImpl.list(QueryTranslatorImpl.java:936)
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
    ... 20 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column '2L' in 'where clause'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.Util.getInstance(Util.java:384)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3562)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3494)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1960)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2114)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2696)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2105)
    at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2264)
    at com.jolbox.bonecp.PreparedStatementHandle.executeQuery(PreparedStatementHandle.java:179)
    at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
    at org.hibernate.loader.Loader.getResultSet(Loader.java:1869)
    at org.hibernate.loader.Loader.doQuery(Loader.java:718)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
    at org.hibernate.loader.Loader.doList(Loader.java:2449)
    ... 27 more

Role和Permission类已与JPA和一些Hibernate注释映射,如下所示:

public abstract class Role implements Serializable {

 /**
  * The id of this role. Internal use only.
  * 
  * @since 1.0
  */
 @Id @GeneratedValue
 protected long id;

 /**
  * Set of permissions granted to this role.
  * 
  * @since 1.0
  */
 @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy="sourceRole")
 protected Set<Permission> permissions = new HashSet<Permission>();

...

}

public class Permission implements Serializable {
 private static final long serialVersionUID = 1L;

 /**
  * The id of this permission. Used internally for persistence.
  * 
  * @since 1.0
  */
 @Id @GeneratedValue
 @Column(name = "PERMISSION_ID")
 protected long id;

 /**
  * The group to which the owner of this permission is being granted permission to.
  * 
  * @since 1.0
  */
 @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
 @JoinColumn(name = "TARGET_ROLE_ID")
 @ForeignKey(name = "FK_TARGET_GROUP_PERMISSION_ID",
   inverseName = "FK_PERMISSION_ID_TARGET_GROUP")
 protected Group targetGroup;

 /**
  * The role that has been granted this permission.
  * 
  * @since 1.0
  */
 @ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
 @JoinColumn(name = "SOURCE_ROLE_ID")
 @ForeignKey(name = "FK_SOURCE_GROUP", inverseName = "FK_GROUP_PERMISSIONS")
 private Role sourceRole;

...

}

此条件查询有什么问题?

我期待对typedQuery.getResultList()的调用返回仅包含一个元素的集合的列表:ID = 2的角色的权限对象的集合。这是试图仅选择(并初始化)“权限”从id = 2的对象角色收集。

我是标准查询的新手,而且很难找到问题所在。

跟进:这是Hibernate试图执行的查询:

select permission1_.PERMISSION_ID as PERMISSION1_12_,
    permission1_.IS_REQUIRED as IS2_12_,
    permission1_.SOURCE_ROLE_ID as SOURCE3_12_,
    permission1_.TARGET_ROLE_ID as TARGET4_12_
from (
        select ROLE_ID,
        NAME,
        DESCRIPTION,
        IS_ACTION,
        LABEL,
        null as FIRST_NAME,
        null as LAST_NAME,
        null as PASSWORD_HASH,
        1 as clazz_ from GROUPS
    union
        select ROLE_ID,
            NAME,
            null as DESCRIPTION,
            null as IS_ACTION,
            null as LABEL,
            FIRST_NAME,
            LAST_NAME,
            PASSWORD_HASH,
            2 as clazz_ from USERS
    )
role0_ inner join PERMISSIONS permission1_ on role0_.ROLE_ID=permission1_.SOURCE_ROLE_ID
    where (role0_.ROLE_ID=2L )

显然问题出在2L。 从MySQL的角度来看,2L实际上是一个字符串或一列,因为它上面带有L并且没有被引用。

这是Hibernate中的错误吗? 在我看来就像一个。 L不应出现在生成的SQL查询中...

任何人都对发生的事情有任何想法吗? 在我看来,这将是一个重大错误,所有其他人都不会忽视这一错误,因此,我假设存在一个很好的变化,我做错了什么。

谢谢!!

爱德华多

您可以为创建联接条件的两个表尝试使用别名。 这也可能是问题,因为休眠仅为HQL和实体负载创建别名,但条件取决于用户来创建别名。

通过将id属性数据类型从long替换为Long解决了该问题。 这个简单的更改使Hibernate开始在查询中放置不带L的2,并且不再发生任何故障。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM