如何强制Hibernate为生成的SQL语句添加引号?

问题描述:

Hibernate正在为特定的条件查询生成无效的SQL。我可以通过向WHERE子句中使用的值添​​加单引号来手动修复查询。如何强制Hibernate为生成的SQL语句添加引号?

where (role0_.ROLE_ID=2L) 

到:

为了解决这个问题,我从改变查询

where (role0_.ROLE_ID=`2L`) 

如何强制休眠添加单引号(在MySQL中是单引号,但在其他数据库系统它可能是其他的东西)来包含在生成的SQL查询中使用的

完整生成的查询是:

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) 

基本上我想由Hibernate加入这个单引号。

生成此查询的条件查询:

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(idAttrPath, new Long(2)) 
Predicate predicate = criteriaBuilder.equal(idAttrPath, 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(); 

请让我知道如果你有关于如何强制Hibernate的单引号添加至值(而不是列/表名)的任何线索。

在我的实体角色中,出现在WHERE子句中的id属性当然是long类型的。

追问:类型在数据库中的id列的是bingint:

+---------------+--------------+------+-----+---------+-------+ 
| Field   | Type   | Null | Key | Default | Extra | 
+---------------+--------------+------+-----+---------+-------+ 
| ROLE_ID  | bigint(20) | NO | PRI | NULL |  | 

... 

这是怎样的角色类已经被注释:

@Entity(name="Role") 
@Table(name = "ROLES") 
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
@javax.persistence.TableGenerator(
    name="GENERATED_IDS", 
    table="GENERATED_IDS", 
    valueColumnName = "ID" 
) 
public abstract class Role implements Serializable { 
    private static final long serialVersionUID = 1L; 


    /** 
    * The id of this role. Internal use only. 
    * 
    * @since 1.0 
    */ 
    @Id @GeneratedValue(strategy = GenerationType.TABLE, generator="GENERATED_IDS") 
    @Column(name = "ROLE_ID") 
    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>(); 

... 

} 

我用每类表继承策略,这就是为什么您在用户和组实体的生成查询中看到联合的原因。他们扩展角色。 Id在角色中定义。

谢谢!

爱德华

+0

我不认为蜱或报价是你的问题就在这里。你为什么使用bigint(20)来存储ID?你可以发布你的映射或注释实体吗? – hisdrewness 2010-10-29 04:02:20

+0

@hisdrewness:当然,我已将注释类部分添加到帖子中。谢谢您的回复! – 2010-10-29 04:35:25

+0

看起来你可以将你的id改为“Long”类而不是原始类。然后Hibernate将简单地生成查询为ROLE_ID = 2,这是100%有效的,因为数字不需要刻度或引号。 – hisdrewness 2010-10-29 14:26:40

更改您的ID为Long类类型,而不是原始的。然后Hibernate将简单地生成查询为ROLE_ID = 2,这是100%有效的,因为数字不需要刻度或引号。

+0

这就是诀窍!谢谢! – 2010-10-30 18:17:58

+0

@Eduardo:很高兴你解决了它。我也喜欢你阅读这个答案,它的相关性有点。 – 2010-11-02 08:52:06

的Hibernate属性hibernate.globally_quoted_identifiers =真会做的伎俩