2011-07-27 16 views
10

mediante la API de criterios, tengo una consulta que hace algo como:JPA2 Criterios API .as (String.class) casting a char (1) - ¿Cómo puedo solucionar esto?

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<SourcePath> pathQuery = cb.createQuery(SourcePath.class); 
Root<SourcePath> pathRoot = pathQuery.from(SourcePath.class); 
pathQuery.where(cb.equal(cb.literal(0x00010002).as(String.class), (pathRoot.get(SourcePath_.path)))); 

TypedQuery<SourcePath> query = entityManager.createQuery(pathQuery); 
query.getResultList(); 

El resultado de la consulta SQL resultante algo como:

select ...snip aliases... from SourcePath where cast(x'00010002', char(1)) = path; 

(ruta habría algún alias malo y viejo, pero eso es irrelevante)

Esta consulta es incorrecta. En particular, el reparto: cast(x'00010002', char(1)) no es un molde a como cadena, según lo especificado por .as(String.class), sino que debe ser cast(x'00010002', char), o cast(x'00010002', char(N) donde N es un número suficientemente grande de manera adecuada.

He aislado la causa de esta falla de conversión al MySqlDialect proporcionado por org.hibernate. Particularmente:

public String getCastTypeName(int code) { 
    if (code==Types.INTEGER) { 
     return "signed"; 
    } 
    else if (code==Types.VARCHAR) { 
     return "char"; 
    } 
    ...snip... 
} 

Qué más abajo en la cadena se interpreta como un char, que está registrado por el diálogo: registerColumnType(Types.CHAR, "char(1)");.

Finalmente, a mi pregunta. ¿Cómo puedo evitar este comportamiento? ¿Lo reporto como un error para Hibernate? ¿Extiendo el cuadro de diálogo y corrijo el tipo devuelto de getCastTypeName? ¿Hay una alternativa al .as que se lanzará adecuadamente? O, si utilizo cadenas en todas partes, actualmente estoy usando valores hexadecimales para evitar tocar casos extremos de la implementación de hibernate.

Gracias BID

+0

Extendiendo el dialecto parece que sería la más fácil camino a seguir. – telm

+0

o arregla el dialecto, plantea un problema en hibernate JIRA y envía tu corrección. – Justin

+0

Extiende el dialecto o usa cadenas en todas partes hasta que se solucione el error. Levanta una JIRA. –

Respuesta

1

en mi humilde opinión, debe utilizar una cadena literal como cb.literal("\u0001\u0002"). Razones:

  1. Es lo mismo que cb.literal(0x00010002).as(String.class), pero menos detallado.
  2. No toca ninguna "carcasa de borde"
  3. Es más claro: ¿se trata "0x00010002" en Big Endian o LE? ¿Qué codificación debería usarse?
  4. Puede mejorar la legibilidad mediante el uso de constantes (por ejemplo, cb.literal(ASCII_SOH + ASCII_STX) donde SOH = "\ u0001" y STX = "\ u0002").

EDIT: Adición de una mejor descripción, ya que no vi la "O, debería utilizar cadenas en todas partes actualmente estoy usando valores hexadecimales"

+0

Mencioné esto en mi pregunta: "O, si utilizo cadenas en todas partes, estoy usando valores hexadecimales para evitar ...". Ciertamente es una opción. – idbentley

+0

Lo siento. Hice mi "opinión" más formal ahora –

Cuestiones relacionadas