Jak uniknąć ostrzeżeń o bezpieczeństwie typu z wynikami Hibernate HQL?

Na przykład mam takie zapytanie:

Query q = sess.createQuery("from Cat cat");
List cats = q.list();

Jeśli spróbuję zrobić coś takiego, wyświetli się Ostrzeżenie "bezpieczeństwo typu: wyrażenie listy typów wymaga niezaznaczonej konwersji, aby było zgodne z listą":

List<Cat> cats = q.list();

Czy jest sposób, aby tego uniknąć?

Author: Paul Bellora, 2008-09-22

16 answers

Używanie @SuppressWarnings wszędzie, zgodnie z sugestią, jest dobrym sposobem, aby to zrobić, chociaż wymaga to odrobiny pisania palcem za każdym razem, gdy dzwonisz q.list().

Są trzy inne techniki, które proponuję:

Collections.checkedList()

Zamień swoje zadanie na to:

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

Możesz sprawdzić javadoc dla tej metody , szczególnie w odniesieniu do equals i hashCode.

Napisz cast-helper

Po prostu refaktoruj wszystkie swoje @SuppressWarnings w jednym miejscu:

List<Cat> cats = MyHibernateUtils.listAndCast(q);

...

public static <T> List<T> listAndCast(Query q) {
    @SuppressWarnings("unchecked")
    List list = q.list();
    return list;
}

Uniemożliwić Eclipse generowanie ostrzeżeń o nieuniknionych problemach

W Eclipse, przejdź do Window>Preferences>Java>Compiler>Errors / Warnings i w obszarze Generic type wybierz checkbox Ignore unavoidable generic type problems due to raw APIs

Spowoduje to wyłączenie niepotrzebnych ostrzeżeń o podobnych problemach, takich jak opisany powyżej, które są nieuniknione.

Kilka komentarzy:

  • wybrałem zdanie Query zamiast wyniku q.list() ponieważ w ten sposób ta metoda "oszukiwania" może być używana tylko do oszukiwania z Hibernate, a nie do oszukiwania jakichkolwiek List w ogóle.
  • możesz dodać podobne metody dla .iterate() itp.
 94
Author: Matt Quail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-01 09:35:13

Minęło sporo czasu odkąd zadano pytanie, ale mam nadzieję, że moja odpowiedź może być pomocna dla kogoś takiego jak ja.

Jeśli spojrzysz na javaxa.persistence API docs , zobaczysz, że niektóre nowe metody zostały tam dodane od Java Persistence 2.0. Jednym z nich jest createQuery(String, Class<T>), który zwraca TypedQuery<T>. Możesz użyć TypedQuery tak jak to zrobiłeś z Query z tą małą różnicą, że wszystkie operacje są teraz bezpieczne.

Więc po prostu zmień swój kod na smth w ten sposób:

Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();

I ty wszystko gotowe.

 22
Author: antonpp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-15 20:24:00

Używamy również @SuppressWarnings("unchecked"), ale najczęściej staramy się go używać tylko na deklaracji zmiennej, a nie na metodzie jako całości:

public List<Cat> findAll() {
    Query q = sess.createQuery("from Cat cat");
    @SuppressWarnings("unchecked")
    List<Cat> cats = q.list();
    return cats;
}
 21
Author: cretzel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 16:55:18

Spróbuj użyć TypedQuery zamiast Query. Na przykład zamiast tego: -

Query q = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q.list();

Użyj tego:-

TypedQuery<Cat> q1 = sess.createQuery("from Cat cat", Cat.class);
List<Cat> cats = q1.list();
 7
Author: shivam oberoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-05 12:28:16

W naszym kodzie opisujemy metody wywołujące za pomocą:

@ SuppressWarnings ("unchecked")

Wiem, że to wygląda na włamanie, ale współtwórca sprawdził niedawno i stwierdził, że to wszystko, co mogliśmy zrobić.

 5
Author: tyshock,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 15:57:42

Najwyraźniej, zapytanie.metoda list () w API Hibernate nie jest bezpieczna dla typu "z założenia" i nie ma planów jej zmiany.

Uważam, że najprostszym rozwiązaniem, aby uniknąć ostrzeżeń kompilatora, jest dodanie @SuppressWarnings ("unchecked"). Ta adnotacja może być umieszczona na poziomie metody lub, jeśli wewnątrz metody, tuż przed deklaracją zmiennej.

W przypadku, gdy masz metodę, która enkapsuluje zapytanie.list () i returns List (lub Collection), otrzymujesz również Ostrzeżenie. Ale ten jest tłumiony za pomocą @SuppressWarnings ("rawtypes").

Metoda listAndCast (zapytanie) zaproponowana przez Matta przepiórki jest mniej elastyczna niż zapytanie.list(). While I can do:

Query q = sess.createQuery("from Cat cat");
ArrayList cats = q.list();

Jeśli wypróbuję poniższy kod:

Query q = sess.createQuery("from Cat cat");
ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);

Dostanę błąd kompilacji: type mismatch: cannot convert from List to ArrayList

 5
Author: Paulo Merson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:39

To nie przeoczenie czy pomyłka. Ostrzeżenie odzwierciedla prawdziwy podstawowy problem - nie ma mowy, aby kompilator Javy mógł być pewien, że Klasa hibernate wykona swoją pracę prawidłowo i że lista, którą zwraca, będzie zawierała tylko koty. Wszelkie sugestie tutaj są w porządku.

 4
Author: paulmurray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-13 02:55:37

Nie, ale możesz wyodrębnić go w konkretne metody zapytań i wyłączyć ostrzeżenia za pomocą adnotacji @SuppressWarnings("unchecked").

 2
Author: Dave L.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 15:58:50

Mieliśmy ten sam problem. Ale nie było to dla nas nic wielkiego, ponieważ musieliśmy rozwiązać inne bardziej poważne problemy z zapytaniem Hibernate i sesją.

Konkretnie:

  1. Kontrola, kiedy transakcja może zostać zrealizowana. (chcieliśmy policzyć ile razy tx został " uruchomiony "i zatwierdzić tylko wtedy, gdy tx został" zakończony " tyle samo razy, ile razy został uruchomiony. Przydatne dla kodu, który nie wie, czy trzeba rozpocząć transakcję. Teraz każdy kod, który potrzebuje tx po prostu "uruchamia" jeden i kończy go kiedy skończymy.)
  2. zbieranie metryk wydajności.
  3. opóźnianie rozpoczęcia transakcji, dopóki nie będzie wiadomo, że coś faktycznie zostanie zrobione.
  4. bardziej delikatne zachowanie dla zapytania.uniqueResult ()

Więc dla nas mamy:

  1. Tworzenie interfejsu (AmplafiQuery), który rozszerza zapytanie
  2. Utwórz klasę (AmplafiQueryImpl), która rozszerza AmplafiQuery i owija org.hibernacja.Query
  3. tworzy Txmanager, który zwraca Tx.
  4. Tx ma różne metody createQuery i zwraca AmplafiQueryImpl

I na koniec

AmplafiQuery ma "asList ()", która jest generyczną włączoną wersją zapytania.lista() AmplafiQuery posiada "unique ()", która jest generyczną włączoną wersją Query.uniqueResult() ( i tylko rejestruje problem zamiast rzucać wyjątek)

To dużo pracy na unikanie @ SuppressWarnings. Jednak, jak powiedziałem (I wymienione) jest wiele innych lepszych! powody, dla których warto wykonać pakowanie.

 1
Author: Pat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-13 02:08:02

Nowsze wersje Hibernate obsługują teraz obiekt type safe Query<T>, więc nie musisz już używać @SuppressWarnings ani implementować hacków, aby ostrzeżenia kompilatora zniknęły. W API sesji , Session.createQuery zwróci teraz obiekt type safe Query<T>. Możesz go użyć w ten sposób:

Query<Cat> query = session.createQuery("FROM Cat", Cat.class);
List<Cat> cats = query.list();

Można go również użyć, gdy wynik zapytania nie zwróci kota:

public Integer count() {
    Query<Integer> query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class);
    return query.getSingleResult();
}

Lub podczas wykonywania częściowego wyboru:

public List<Object[]> String getName() {
    Query<Object[]> query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class);
    return query.list();
}
 1
Author: David DeMar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-07 15:11:27

Rozwiązanie Joe Deana wygląda ciekawie, ale czy uważasz, że warto-stworzyć nową listę i przebić się przez wszystkie elementy tylko po to, aby pozbyć się ostrzeżeń?

(sorry, can ' t add a comment directly to his solution for some reason)

 0
Author: serg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 16:48:08

Wiem, że to jest starsze, ale 2 punkty do odnotowania na dzień dzisiejszy w Matt Quails odpowiedzi.

Punkt 1

To

List<Cat> cats = Collections.checkedList(Cat.class, q.list());

Powinno być to

List<Cat> cats = Collections.checkedList(q.list(), Cat.class);

Punkt 2

Z tego

List list = q.list();

Do tego

List<T> list = q.list();

Zmniejszyłoby inne ostrzeżenia, oczywiście w oryginalnych znacznikach odpowiedzi, które zostały usunięte przez przeglądarkę.

 0
Author: Tony Shih,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-01 23:56:35

Spróbuj tego:

Query q = sess.createQuery("from Cat cat");
List<?> results = q.list();
for (Object obj : results) {
    Cat cat = (Cat) obj;
}
 -1
Author: Brian Ngure,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 21:53:05

Dobrym rozwiązaniem, aby uniknąć ostrzeżeń o bezpieczeństwie typu za pomocą zapytania hibernate, jest użycie narzędzia typu TorpedoQuery, które pomoże Ci zbudować bezpieczny Typ hql.

Cat cat = from(Cat.class);
org.torpedoquery.jpa.Query<Entity> select = select(cat);
List<Cat> cats = select.list(entityManager);
 -1
Author: xjodoin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-11 18:54:00
TypedQuery<FDPCDRDetails> createQuery = entityManager.createQuery("from FDPCDRDetails", FDPCDRDetails.class);
List<FDPCDRDetails> resultList = createQuery.getResultList();
 -1
Author: Rakesh Singh Balhara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-17 05:56:26

Jeśli nie chcesz używać @SuppressWarnings ("unchecked"), możesz wykonać następujące czynności.

   Query q = sess.createQuery("from Cat cat");
   List<?> results =(List<?>) q.list();
   List<Cat> cats = new ArrayList<Cat>();
   for(Object result:results) {
       Cat cat = (Cat) result;
       cats.add(cat);
    }

FYI-stworzyłem metodę util, która robi to za mnie, aby nie zaśmiecać mojego kodu i nie muszę używać @SupressWarning.

 -5
Author: Joe Dean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-22 16:34:04