使用非实体 class 作为本机查询的结果 class
use a non-entity class as a result class for native query
网络上的每个 example/tutorials 都处理实体 classes,当涉及存储过程(函数)时,SP 仅从该实体收集数据。虽然这很常见,但我们有一个涉及多个表的复杂查询,并且我们希望返回一些列。为此,我们可以在 postgresql 中使用带或不带任何参数的函数。
我有这段调用这样一个函数的代码:
@Component
public class CapPlanningItemPerCapGroupImpl implements CapPlanningItemPerCapGroupRepository {
private final EntityManager em;
public CapPlanningItemPerCapGroupImpl(EntityManager em) {
this.em = em;
}
@Override
public List<CapPlanningItemPerCapGroup> getCapPlanningItems(Long companyId, Long plantId, int year, Long costAccTypeId) {
Session session = em.unwrap(Session.class);
NativeQuery<CapPlanningItemPerCapGroup> query = session.createNativeQuery(
"SELECT * FROM get_cap_planning_items(:year, :companyId, :plantId, :costAccTypeId)", CapPlanningItemPerCapGroup.class);
query.setParameter("year", year);
query.setParameter("companyId", companyId);
query.setParameter("plantId", plantId);
query.setParameter("costAccTypeId", costAccTypeId);
return query.getResultList();
}
}
CapPlanningItemPerCapGroup
class 没有用 @Entity
注释,因为我不想将它作为数据表存储在数据库中。这就像一个自定义类型。但是使用这个设置,上面的查询失败了,说 CapPlanningItemPerCapGroup
是一个未知的实体。
如果我从查询调用中删除此 CapPlanningItemPerCapGroup.class
,我会在邮递员中得到结果,但当然没有任何字段名称,只有原始数据。
所以,我的问题是:我真的需要手动将结果列表转换为 appr. class 类型,或者是否有开箱即用的自动映射,我不必列出所有返回的列名和类型?
谢谢。
您可以使用 @SqlResultSetMapping
来描述 Hibernate 将对结果集中的每条记录执行的构造函数调用。我在我的博客 Result Set Mapping: Constructor Result Mappings 中详细解释了这一点。
大意很简单:
您的 CapPlanningItemPerCapGroup
需要一个设置所有属性的构造函数。
在 @SqlResultSetMapping
中,您通过引用 class 来描述构造函数调用,并按照您希望将它们提供给构造函数的顺序列出结果集中的列,例如:
@SqlResultSetMapping(
name = "BookValueMapping",
classes = @ConstructorResult(
targetClass = BookValue.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "title"),
@ColumnResult(name = "version", type = Long.class),
@ColumnResult(name = "authorName")}))
定义映射后,您可以将其名称作为第二个参数提供给 createNativeQuery
方法。
List<BookValue> results = this.em.createNativeQuery("SELECT b.id, b.title, b.version, a.firstName || a.lastName as authorName FROM Book b JOIN Author a ON b.author_id = a.id", "BookValueMapping").getResultList();
网络上的每个 example/tutorials 都处理实体 classes,当涉及存储过程(函数)时,SP 仅从该实体收集数据。虽然这很常见,但我们有一个涉及多个表的复杂查询,并且我们希望返回一些列。为此,我们可以在 postgresql 中使用带或不带任何参数的函数。
我有这段调用这样一个函数的代码:
@Component
public class CapPlanningItemPerCapGroupImpl implements CapPlanningItemPerCapGroupRepository {
private final EntityManager em;
public CapPlanningItemPerCapGroupImpl(EntityManager em) {
this.em = em;
}
@Override
public List<CapPlanningItemPerCapGroup> getCapPlanningItems(Long companyId, Long plantId, int year, Long costAccTypeId) {
Session session = em.unwrap(Session.class);
NativeQuery<CapPlanningItemPerCapGroup> query = session.createNativeQuery(
"SELECT * FROM get_cap_planning_items(:year, :companyId, :plantId, :costAccTypeId)", CapPlanningItemPerCapGroup.class);
query.setParameter("year", year);
query.setParameter("companyId", companyId);
query.setParameter("plantId", plantId);
query.setParameter("costAccTypeId", costAccTypeId);
return query.getResultList();
}
}
CapPlanningItemPerCapGroup
class 没有用 @Entity
注释,因为我不想将它作为数据表存储在数据库中。这就像一个自定义类型。但是使用这个设置,上面的查询失败了,说 CapPlanningItemPerCapGroup
是一个未知的实体。
如果我从查询调用中删除此 CapPlanningItemPerCapGroup.class
,我会在邮递员中得到结果,但当然没有任何字段名称,只有原始数据。
所以,我的问题是:我真的需要手动将结果列表转换为 appr. class 类型,或者是否有开箱即用的自动映射,我不必列出所有返回的列名和类型?
谢谢。
您可以使用 @SqlResultSetMapping
来描述 Hibernate 将对结果集中的每条记录执行的构造函数调用。我在我的博客 Result Set Mapping: Constructor Result Mappings 中详细解释了这一点。
大意很简单:
您的 CapPlanningItemPerCapGroup
需要一个设置所有属性的构造函数。
在 @SqlResultSetMapping
中,您通过引用 class 来描述构造函数调用,并按照您希望将它们提供给构造函数的顺序列出结果集中的列,例如:
@SqlResultSetMapping(
name = "BookValueMapping",
classes = @ConstructorResult(
targetClass = BookValue.class,
columns = {
@ColumnResult(name = "id", type = Long.class),
@ColumnResult(name = "title"),
@ColumnResult(name = "version", type = Long.class),
@ColumnResult(name = "authorName")}))
定义映射后,您可以将其名称作为第二个参数提供给 createNativeQuery
方法。
List<BookValue> results = this.em.createNativeQuery("SELECT b.id, b.title, b.version, a.firstName || a.lastName as authorName FROM Book b JOIN Author a ON b.author_id = a.id", "BookValueMapping").getResultList();