2011-07-27 7 views
10

używając API kryteria, mam kwerendę, która robi coś takiego:Metoda API JPA2 Criteria .as (String.class) do char (1) - jak to obejść?

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

Powstały wyniki kwerendy SQL coś jak:

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

(ścieżka byłaby rzęsiste stary alias, ale to bez znaczenia).

To zapytanie jest nieprawidłowe. W szczególności obsada: cast(x'00010002', char(1)) nie jest rzutowana na ciąg znaków, jak określono w .as(String.class), zamiast tego powinna być albo cast(x'00010002', char), albo cast(x'00010002', char(N), gdzie N jest odpowiednio dużą liczbą.

Izolowałem przyczynę tego odrzuconego błędu w MySqlDialect dostarczonym przez org.hibernate. Szczególnie:

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

Co dalej w dół łańcucha jest interpretowana jako char, która została zarejestrowana przez okna: registerColumnType(Types.CHAR, "char(1)");.

Wreszcie na moje pytanie. Jak mogę obejść to zachowanie? Czy zgłoszę go jako błąd do Hibernacji? Czy mogę rozszerzyć okno dialogowe i poprawić zwracany typ z getCastTypeName? Czy istnieje alternatywa dla .as, która będzie odpowiednio rzutować? Czy też powinienem używać ciągów wszędzie, gdzie obecnie używam wartości szesnastkowych, aby uniknąć dotykania krawędzi przypadków implementacji hibernacji?

Dzięki IDB

+0

Rozszerzanie dialekt Wygląda byłoby najprostszym droga iść. – telm

+0

lub naprawić dialekt, podnieść problem na hibernacji JIRA i przesłać poprawkę. – Justin

+0

Rozszerz dialekt lub użyj ciągów wszędzie, aż błąd zostanie naprawiony. Podnieś JIRA. –

Odpowiedz

1

IMHO, należy użyć ciągu dosłownego jak cb.literal("\u0001\u0002"). Powody:

  1. To samo, co cb.literal(0x00010002).as(String.class), ale mniej gadatliwy.
  2. Nie uderza w żadną "skrzynkę krawędziową"
  3. Jest wyraźniejsza: czy "0x00010002" jest traktowane w Big Endian lub LE? Którego kodowania należy użyć?
  4. Możesz poprawić czytelność za pomocą stałych (np .: cb.literal(ASCII_SOH + ASCII_STX) gdzie SOH = "\ u0001" i STX = "\ u0002").

EDIT: Dodawanie lepszy opis, bo nie widzi „albo należy użyć ciągi wszędzie obecnie używam HEX-wartości”

+0

Wspomniałem o tym w moim pytaniu: "Albo, czy powinienem używać ciągów wszędzie, gdzie obecnie używam wartości szesnastkowych, aby uniknąć ...". To na pewno jest opcja. – idbentley

+0

Przepraszam za to. Zrobiłem teraz "opinię" bardziej formalną –

Powiązane problemy