使用 JPA 2.1,我如何将本机查询结果映射到 @Transient 字段(taht is a Set)?
Posted
技术标签:
【中文标题】使用 JPA 2.1,我如何将本机查询结果映射到 @Transient 字段(taht is a Set)?【英文标题】:Using JPA 2.1, how do I map a native query result to a @Transient field taht is a Set? 【发布时间】:2015-04-10 20:06:03 【问题描述】:我正在使用 JPA 2.1、Hibernate 4.1.3.Final 和 mysql 5.5.37。如何将结果集映射到 @Transient
集合?在我的实体中,我已经设置了
@Entity
@Table(name = "category", uniqueConstraints = @UniqueConstraint(columnNames = "NAME", "PD_ONLY" ) )
@SqlResultSetMapping(name = "categoryResults", classes = @ConstructorResult(targetClass = org.mainco.subco.core.domain.Category.class, columns =
@ColumnResult(name = "id"), @ColumnResult(name = "name"), @ColumnResult(name = "pd_only"),
@ColumnResult(name = "subjects") ) )
public class Category implements Serializable, Comparable<Category>
@Id
@Column(name = "ID")
@GeneratedValue(generator = "uuid-strategy")
private String id;
private String name;
@Column(name = "PD_ONLY")
private Boolean pdOnly;
@Transient
private Set<Subject> subjects;
然后我尝试使用本机查询来映射事物……
final Query q = m_entityManager.createNativeQuery(
"select distinct c.id, " +
" c.name, " +
" c.pd_only, " +
" e.subject_id FROM category c, " +
" resource_category rc, " +
" product_resource pr, " +
" product p, " +
" product_ebook pe, " +
" book e where c.pd_only = :pdOnly and c.id = rc.category_id and rc.resource_id = pr.resource_id and pr.product_id = p.id and p.id = pe.product_id and pe.ebook_id = e.id and c.id = 'Curriculum Maps';",
"categoryResults")
.setParameter("pdOnly", pdOnly ? "1" : "0");
return q.getResultList();
但我得到以下异常......
javax.persistence.PersistenceException: org.hibernate.HibernateException: Could not resolve column name in result set [subjects]
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1166)
at org.hibernate.loader.custom.JdbcResultMetadata.resolveColumnPosition(JdbcResultMetadata.java:67)
at org.hibernate.loader.custom.ScalarResultColumnProcessor.performDiscovery(ScalarResultColumnProcessor.java:59)
at org.hibernate.loader.custom.ConstructorResultColumnProcessor.performDiscovery(ConstructorResultColumnProcessor.java:58)
at org.hibernate.loader.custom.CustomLoader.autoDiscoverTypes(CustomLoader.java:498)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2073)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838)
at org.hibernate.loader.Loader.doQuery(Loader.java:909)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
at org.hibernate.loader.Loader.doList(Loader.java:2553)
at org.hibernate.loader.Loader.doList(Loader.java:2539)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369)
at org.hibernate.loader.Loader.list(Loader.java:2364)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353)
at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1873)
at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311)
at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:573)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:449)
at org.mainco.subco.core.repo.CategoryDaoImpl.findCategories(CategoryDaoImpl.java:78)
at org.mainco.subco.core.repo.CategoryDaoImpl.findNonPDCategories(CategoryDaoImpl.java:38)
at org.mainco.subco.core.repo.CategoryDaoIT.testFindNonPDCategories(CategoryDaoIT.java:30)
关于如何将从我的本机查询返回的内容映射到结果集中的任何想法?我也愿意不使用原生 SQL 并使用 CriteriaBuilder/JPQL 做一些事情。
【问题讨论】:
您认为如何将一行数据映射到一个集合?每行只有一个“subject_id”,所以您希望每个集合中有 1 个元素? 这就是我问这个问题的原因!我想知道怎么做。 【参考方案1】:您可以将结果列表作为 Object[] 的原始列表。然后,您可以根据需要投射对象并安装实例。
参见下面的代码 sn-p。我没有测试过代码,所以如果你可以尝试一下,请告诉我们结果。
// Here you get the result set as a raw list of objects
@SuppressWarnings("unchecked")
List<Object[]> resultList = nq.getResultList();
// Maybe you will need a set of Category for the "categoryResults"
Set<Category> categoryResults = new HashSet<>();
// Here you cast the whole result set
for (Object[] record : resultList)
// Sets Category
Category category = new Category();
category.setId((Integer) record[0]);
category.setName((String) record[1]);
category.setPdOnly((Boolean) record[2]);
// Sets Subject
Subject subject = new subject();
subject.setId((Integer) record[3]);
// Adds Subject to the HashSet
Set<Subject> subjectsSet = new HashSet<>();
subjectsSet.add(subject);
// Here you have what you need, the setting of the transient field
category.setSubjects(subjectsSet);
// Finally adds category onto results
categoryResults.add(category);
【讨论】:
以上是关于使用 JPA 2.1,我如何将本机查询结果映射到 @Transient 字段(taht is a Set)?的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA 将原生查询结果映射到非实体 POJO
EclipseLink 拒绝将 PostgreSQL 上的本机查询映射到实体
JPA 2.1 中的 @ConstructorResult 映射不能与 Hibernate 4.3.5.Final 一起正常工作