Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nice way to select a tuple using JPA

final List<Tuple> data =
                    em.createQuery("SELECT p.id AS i, p.membership AS m FROM Player p WHERE p.id IN :ids", Tuple.class)
                    .setParameter("ids", ids)
                    .getResultList();

This gives the error "Cannot create TypedQuery for query with more than one return". I could work around that by leaving out the type parameter (and using Object[] instead of Tuple, as I later found out):

@SuppressWarnings("unchecked")
final List<Object[]> data =
                    em.createQuery("SELECT p.id AS i, p.membership AS m FROM Player p WHERE p.id IN :ids")
                    .setParameter("ids", ids)
                    .getResultList();

But is there a solution that doesn't require unchecked code?

like image 505
Bart van Heukelom Avatar asked Dec 29 '11 12:12

Bart van Heukelom


People also ask

What is tuple in JPA?

In JPA Criteria API, Tuple provides another way to select multiple values. Tuple contains ordered query results which can be access via index, type, alias and TupleElement. A query involving Tuple can be created by using following method of CriteriaBuilder : CriteriaQuery<Tuple> createTupleQuery();

What are three methods to execute queries in JPA?

There are three basic types of JPA Queries:Query, written in Java Persistence Query Language (JPQL) syntax. NativeQuery, written in plain SQL syntax. Criteria API Query, constructed programmatically via different methods.


1 Answers

A tuple isn't really any more typesafe than an array, is it?

What you could do here is use a constructor expression. Off the top of my head, this is something like:

class PlayerMembership {
    public final int id;
    public final MembershipType membership;
    public PlayerMembership(int id, MembershipType membership) {
        this.id = id;
        this.membership = membership;
    }
}

List<PlayerMembership> data =
                    em.createQuery("SELECT NEW nl.bart.PlayerMembership(p.id, p.membership) FROM Player p WHERE p.id IN :ids", PlayerMembership.class)
                    .setParameter("ids", ids)
                    .getResultList();

This requires you to write a new class to hold the result, but this will typically be pretty trivial.

like image 71
Tom Anderson Avatar answered Sep 26 '22 08:09

Tom Anderson