Чтение из нескольких таблиц и заполнение нескольких сущностей с использованием JPA SqlResultSetMapping
Я создавал приложение JSF, используя JPA для доступа к БД. Есть ряд сущностей.
Я хочу создать экран результатов поиска, который показывает столбцы из более чем одного объекта в таблице. Эти объекты не имеют отношений с внешним ключом.
Для достижения этого я использовал EnttityManager.createNativeQuery и указал EntityMapping, например, так:
Query q = em.createNativeQuery(
"select t.id as id1, t.bb as bb1, t.cc as cc1," +
"t2.id as id2, t2.aa as aa2, t2.bb as bb2 " +
" from table1 t, table2 t2 where t.cc = '22' and t2.id = 2", "TestMapping");
result = q.getResultList();
TestMapping выглядит так:
@SqlResultSetMapping(name =
"TestMapping", entities = {
@EntityResult(entityClass = Table1.class, fields = {
@FieldResult(name = "id", column = "id1"),
@FieldResult(name = "bb", column = "bb1"),
@FieldResult(name = "cc", column = "cc1")}
),
@EntityResult(entityClass = Table2.class, fields = {
@FieldResult(name = "id", column = "id2"),
@FieldResult(name = "aa", column = "aa2"),
@FieldResult(name = "bb", column = "bb2")}
)
} )
Это работает, если я указываю все имена столбцов из обоих объектов в запросе, что хорошо в этом небольшом примере, но результаты поиска должны выбирать из 4 объектов, каждый из которых имеет большое количество столбцов. Если я не указываю все столбцы в EntityMapping, в вызове getResultList() выдается исключение.
У меня такой вопрос: возможно ли указывать только те столбцы в EntityMapping, которые выбраны в запросе, а не указывать все из сущностей?
2 ответа
Я не знаю, работает ли это со всеми реализациями JPA. Если вы используете Hibernate, вы можете сопоставить все свои свойства с ленивым типом выборки:
@Basic(fetch = FetchType.LAZY)
Date dateCreated;
@Column(length=100)
@Basic(fetch = FetchType.LAZY)
String name;
Затем вам нужно обработать ваш класс, иначе он проигнорирует ленивые свойства:
<target name="instrument" depends="compile">
<taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask">
<classpath path="${jar.path}"/>
<classpath path="${classes.dir}"/>
<classpath refid="lib.class.path"/>
</taskdef>
<instrument verbose="true">
<fileset dir="${testclasses.dir}/org/hibernate/auction/model">
<include name="*.class"/>
</fileset>
</instrument>
Или вы также можете использовать синтаксис entity.* Для одновременного указания всех столбцов объекта:
Query q = em.createNativeQuery("select t.*, t2.*" + " from table1 t, table2 t2"+
"where t.cc = '22' and t2.id = 2", "TestMapping");
И TestMapping:
@SqlResultSetMapping(name = "TestMapping",
entities = { @EntityResult(entityClass =Table1.class),
@EntityResult(entityClass =Table2.class)})