JPA Query.getResultList() - используется в общем виде
Я создаю сложный запрос с несколькими таблицами и должен перечислять результат. Обычно я использую EntityManager
и сопоставляю результат с JPA-представлением:
UserEntity user = em.find(UserEntity.class, "5");
Затем я могу получить доступ ко всем значениям, так как это определяет класс пользователя UserEntity
. Но как я могу получить доступ к значениям полей, возвращенным из собственного запроса с несколькими таблицами? Я получаю список объектов. До сих пор это прекрасно, но что такое "этот"? Массив? Карта? Коллекция?...
//simpleExample
Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id");
List list = query.getResultList();
//do sth. with the list, for example access "something" for every result row.
Я думаю, ответ довольно прост, но большинство примеров там просто показывают использование при прямом нажатии на targetClass.
PS: В этом примере я мог бы, конечно, использовать сопоставления классов. Но в моем случае someTable
не управляется JPA, и поэтому у меня нет объекта и у меня нет его представления класса, и поскольку я присоединяюсь к 20 таблицам, я не хочу создавать все классы просто для доступа к значениям.
Ответы
Ответ 1
Общее правило следующее:
- Если
select
содержит одиночное выражение, и это объект, то результатом является то, что entity
- Если
select
содержит одно выражение, а это примитив, то результатом является то, что примитивный
- Если
select
содержит несколько выражений, тогда результат Object[]
содержит соответствующие примитивы/сущности
Итак, в вашем случае list
есть List<Object[]>
.
Ответ 2
Так как JPA 2.0 a TypedQuery
может использоваться:
TypedQuery<SimpleEntity> q =
em.createQuery("select t from SimpleEntity t", SimpleEntity.class);
List<SimpleEntity> listOfSimpleEntities = q.getResultList();
for (SimpleEntity entity : listOfSimpleEntities) {
// do something useful with entity;
}
Ответ 3
Вышеприведенный запрос возвращает список Object []. Поэтому, если вы хотите получить u.name и s.something из списка, вам нужно выполнить итерацию и применить эти значения для соответствующих классов.
Ответ 4
Если вам нужен более удобный способ доступа к результатам, он может с легкостью преобразовать результат произвольно сложного SQL-запроса в класс Java:
Query query = em.createNativeQuery("select 42 as age, 'Bob' as name from dual",
MyTest.class);
MyTest myTest = (MyTest) query.getResultList().get(0);
assertEquals("Bob", myTest.name);
Класс должен быть объявлен как @Entity, что означает, что вы должны убедиться, что он имеет уникальный @Id.
@Entity
class MyTest {
@Id String name;
int age;
}
Ответ 5
Вот пример того, что сработало для меня. Я думаю, что метод put необходим в классе сущности для сопоставления столбцов sql с атрибутами класса java.
//simpleExample
Query query = em.createNativeQuery(
"SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id",
NameSomething.class);
List list = (List<NameSomething.class>) query.getResultList();
Класс сущностей:
@Entity
public class NameSomething {
@Id
private String name;
private String something;
// getters/setters
/**
* Generic put method to map JPA native Query to this object.
*
* @param column
* @param value
*/
public void put(Object column, Object value) {
if (((String) column).equals("name")) {
setName(String) value);
} else if (((String) column).equals("something")) {
setSomething((String) value);
}
}
}