Иногда, работая с JPA/ORM фреймворками, например такими как Hibernate возникает необходимость выполнить NativeQuery для какой-то определённой СУБД, но результат хотелось бы иметь, как и в JPQL - в виде одного или списка JPA Entities, а иногда, даже в виде списка POJO. Т.е. например выбрать несколько полей из таблицы и замапить их для удобного использования в специально созданный POJO.
В случае со списком Entities, тут всё довольно просто: следует обратить внимание на слегка изменённый синтаксис:
String q = "SELECT c.* FROM TargetClass c " +
" LEFT JOIN sometable t ON a.someid = t.someid WHERE " +
" c.num = 0 AND t.color = 3 AND t.size < :somesize";
Query query = entityManager.createNativeQuery(q, TargetClass.class);
Если же нам требуется замапить совершенно не привязанные к JPA Entity данные, то можно поступить так: при написании NativeQuery в конце указать Result Set Mapping (здесь указан - "DistrictMapping")
final Query q = em.createNativeQuery("SELECT count(z.id) as cnt, kr.id_district, kr.name" +
"FROM place z, kl_district kr WHERE " +
"z.someid=kr.someid AND ... GROUP BY ... ORDER BY ...",
"DistrictMapping");
и в файле orm.xml указать, собственно сам маппинг:
<entity-mappings version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">
<sql-result-set-mapping name="DistrictMapping">
<constructor-result target-class="info.zaharov.District">
<column name="cnt" class="java.lang.Integer"/>
<column name="id_district" class="java.lang.Integer"/>
<column name="name" class="java.lang.String"/>
</constructor-result>
</sql-result-set-mapping>
</entity-mappings>
Здесь у нас info.zaharov.District это сам POJO, куда будет раскладываться результат и далее - названия колонок в result set из базы(!) с указанием типов.
Обратите внимание - нам нужно использовать JPA 2.1.
И далее, сам POJO:
public class District{
private Integer cnt;
private Integer id_district;
private String name;
public District() {
}
public District(Integer cnt, Integer id_district, String name) {
this.cnt = cnt;
this.id_district = id_district;
this.name = name;
}
// Getters, setters