JPA & Criteria API-wybierz tylko określone kolumny

Chciałbym wybrać tylko konkretne kolumny (np. SELECT a FROM b). Ja mam ogólne DAO i to co wymyśliłem to:

public List<T> getAll(boolean idAndVersionOnly) {
    CriteriaBuilder builder = manager.getCriteriaBuilder();
    CriteriaQuery<T> criteria = builder.createQuery(entityClazz);
    Root<T> root = criteria.from(entityClazz);
    if (idAndVersionOnly) {
        criteria.select(root.get("ID").get("VERSION")); // HERE IS ERROR
    } else {
        criteria.select(root);
    }
    return manager.createQuery(criteria).getResultList();
}

A błąd jest: The method select(Selection<? extends T>) in the type CriteriaQuery<T> is not applicable for the arguments (Path<Object>). Jak mam to zmienić? Chcę otrzymać obiekt type T, który ma tylko pola ID i VERSION, a wszystkie pozostałe to null.

Type T extends AbstractEntity, który ma te 2 pola.

entityClazz is T.class.

Author: Hash, 2012-09-27

4 answers

Jednym ze sposobów uzyskiwania tylko poszczególnych kolumn jest poproszenie o obiekt krotka.

W Twoim przypadku powinieneś napisać coś takiego:

CriteriaQuery<Tuple> cq = builder.createTupleQuery();
// write the Root, Path elements as usual
Root<EntityClazz> root = cq.from(EntityClazz.class);
cq.multiselect(root.get(EntityClazz_.ID), root.get(EntityClazz_.VERSION));  //using metamodel
List<Tuple> tupleResult = em.createQuery(cq).getResultList();
for (Tuple t : tupleResult) {
    Long id = (Long) t.get(0);
    Long version = (Long) t.get(1);
}

Inne podejście jest możliwe, jeśli masz klasę reprezentującą wynik, jak w Twoim przypadku T. T nie musi być klasą encji. Jeśli T ma konstruktor taki jak:

public T(Long id, Long version)

Następnie możesz użyć T bezpośrednio w konstruktorze CriteriaQuery:

CriteriaQuery<T> cq = builder.createQuery(T.class);
// write the Root, Path elements as usual
Root<EntityClazz> root = cq.from(EntityClazz.class);
cq.multiselect(root.get(EntityClazz_.ID), root.get(EntityClazz_.VERSION));  //using metamodel
List<T> result = em.createQuery(cq).getResultList();

Zobacz ten link dla dalsze informacje.

 91
Author: perissf,
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-10-03 08:58:59
cq.select(cb.construct(entityClazz.class, root.get("ID"), root.get("VERSION")));  // HERE IS NO ERROR

Https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Criteria#Constructors

 10
Author: EduardoRamirez,
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-03-26 23:14:51

Po pierwsze, nie rozumiem, dlaczego chcesz, aby obiekt miał tylko ID i wersję, a wszystkie inne rekwizyty były null. Jednak tutaj jest jakiś kod, który zrobi to za Ciebie (który nie używa JPA Em, ale normalnego Hibernate. Zakładam, że można znaleźć równoważność w JPA lub po prostu uzyskać Hibernate session obj od delegata em uzyskiwanie dostępu do sesji hibernacji z EJB przy użyciu EntityManager ):

List<T> results = session.createCriteria(entityClazz)
    .setProjection( Projections.projectionList()
        .add( Property.forName("ID") )
        .add( Property.forName("VERSION") )
    )
    .setResultTransformer(Transformers.aliasToBean(entityClazz); 
    .list();

Zwróci listę obiektów o ustawionym ID i wersji i wszystkie inne rekwizyty do null, ponieważ aliasToBean transformer nie będzie w stanie ich znaleźć. Ponownie, jestem niepewny, mogę myśleć o sytuacji, w której chciałbym to zrobić.

 3
Author: Nikola Yovchev,
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 11:47:18

Możesz zrobić coś takiego

Session session = app.factory.openSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery();
Root<Users> root = query.from(Users.class);
query.select(root.get("firstname"));
String name = session.createQuery(query).getSingleResult();

Gdzie można zmienić "firstname" z nazwą kolumny, którą chcesz.

 -3
Author: Abrar Ansari,
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-12-28 18:00:52