2010-10-29 5 views
2

Hibernate génère un SQL non valide pour une requête de critères particulière. Je peux corriger manuellement la requête en ajoutant des guillemets simples à la valeur utilisée dans la clause WHERE.Comment forcer Hibernate à ajouter des guillemets aux instructions SQL générées?

Pour résoudre ce problème, j'ai changé la requête à partir de:

where (role0_.ROLE_ID=2L) 

à:

where (role0_.ROLE_ID=`2L`) 

Comment forcer veille prolongée à ajouter des guillemets simples (dans une base MySQL, il est entre guillemets simples mais dans d'autres systèmes de bases de données cela peut être quelque chose d'autre) pour inclure les valeurs utilisées dans les requêtes SQL générées?

La requête générée complète est:

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) 

En fait, je voudrais que cela guillemets simples à ajouter par Hibernate.

La requête de critères qui ont généré cette requête est:

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

S'il vous plaît laissez-moi savoir si vous avez des indices sur la façon de forcer Hibernate à ajouter ces guillemets simples aux valeurs (et non la colonne/nom de la table) .

Dans mon rôle d'entité, la propriété id qui apparaît dans la clause WHERE est de type long, bien sûr.

Suivi: Le type de la colonne id dans la base de données est bingint:

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

... 

Voici comment la classe de rôle a été annoté:

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

... 

} 

J'utilise table par classe stratégie d'héritage, c'est pourquoi vous voyez l'union dans la requête générée pour les entités Utilisateur et Groupe. Ils étendent le rôle. Id est défini dans Role.

Merci!

Eduardo

+0

Je ne pense pas que les tiques ou les citations sont votre problème. Pourquoi utilisez-vous bigint (20) pour stocker l'identifiant? Pouvez-vous poster votre carte ou entité annotée? – hisdrewness

+0

@hisdrewness: bien sûr, j'ai ajouté la section de classe annotée au post. Merci pour votre réponse! –

+0

On dirait que vous pouvez simplement changer votre identifiant à la classe 'Long' au lieu d'une primitive. Hibernate va alors simplement générer la requête à ROLE_ID = 2, ce qui est 100% valide puisque les nombres ne nécessitent pas de ticks ou de guillemets. – hisdrewness

Répondre

1

Changez votre identifiant le type de classe Long au lieu d'une primitive. Hibernate va alors simplement générer la requête à ROLE_ID = 2, ce qui est 100% valide puisque les nombres ne nécessitent pas de ticks ou de guillemets.

+0

Ça a fait l'affaire! Je vous remercie! –

+0

@Eduardo: Content que tu l'aies résolu. Je vous aime à lire cette réponse aussi, c'est un peu lié. –

4

La propriété mise en veille prolongée hibernate.globally_quoted_identifiers = true fera l'affaire

Questions connexes