乍一看我有一个简单的问题:
entityManager()
.createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla")
我想将选择结果写入POJO,如下所示:
public class AggregateStatsDto {
private int total;
private long totalSum;
// getters, setters, cosntructors
}
实现这一目标的最佳方法是什么?
我可以使用JPA 2.1并尝试将 @SqlResultSetMapping 与 @ConstructorResult 结合使用:
@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
@ConstructorResult(targetClass = AggregateStatsDto.class,
columns = {
@ColumnResult(name = "total"),
@ColumnResult(name = "totalSum")
})
})
public class AggregateStatsDto {
private long total;
private int totalSum;
// getters, setters, cosntructors
}
查询:
AggregateStatsDto result = (AggregateStatsDto) entityManager()
.createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla", "AggregateStatsResult")
.getSingleResult();
但没有运气。无论如何它似乎想要@Entity。但我只想要一个POJO。
org.hibernate.MappingException: Unknown SqlResultSetMapping [AggregateStatsResult]"
提前致谢!
答案 0 :(得分:9)
将@SqlResultSetMapping批注放在一个实际实体的类中,而不是放在DTO类中。当您在非实体中注释SqlResultSetMapping时,您的实体管理器无法发现您的映射。
@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
@ConstructorResult(targetClass = AggregateStatsDto.class,
columns = {
@ColumnResult(name = "total"),
@ColumnResult(name = "totalSum")
})
})
@Entity
public class SomeOtherClassWhichIsAnEntity {
答案 1 :(得分:6)
我通过以下方式解决了我的问题: 这是一个查询:
final Query query = Sale.entityManager().createNativeQuery(...);
然后我访问了实体管理器内部的Hibernate会话并应用了scalars / resultTransformer。多数民众赞成!
// access to internal Hibernate of EntityManager
query.unwrap(SQLQuery.class)
.addScalar("total", LongType.INSTANCE)
.addScalar("amountOfSales", LongType.INSTANCE)
.addScalar("amountOfProducts", LongType.INSTANCE)
.setResultTransformer(Transformers.aliasToBean(SaleStatsInfo.class));
...
query.getSingleResult();
答案 2 :(得分:0)
这不是建议的方法。上面在@SqlResultSetMapping中提到了更有效的方法,但是如果您想要更硬的东西,则可以通过返回的对象访问实体管理器的结果。
例如:
Query q = getEntityManager().createNativeQuery(queryString);
使用q.getSingleResult();
触发该操作,将带回java.util.HashMap
类型的对象,您可以使用它逐行访问结果。
例如:
Query q = getEntityManager().createNativeQuery(queryString);
java.util.HashMap res = (java.util.HashMap) q.getSingleResult();
for (Object key : res.keySet()) {
System.out.println(key.toString());
System.out.println( res.get(key).toString());
}
答案 3 :(得分:0)
我被困了一段时间。我发现最常见的解决方案如下。不要忘记在createNativeQuery方法的第二个参数上添加映射的名称。这样,您的pojo应该没有注释,但将从实体类中进行映射。
//Place SqlResultSetMapping annotation in Entity class:
@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
@ConstructorResult(targetClass = AggregateStatsDto.class,
columns = {
@ColumnResult(name = "total"),
@ColumnResult(name = "totalSum")
})
})
@Entity
public EntityFromExistingTableInDB{
...fields
}
//1st param is your query, 2nd param is the name of your mapping above
Query query = entityManager.createNativeQuery("yourQuery", "AggregateStatsResult");
答案 4 :(得分:0)
我认为这是最直接的方法。
声明一个 POJO/DTO 并用 @NativeQueryResultEntity
标记它。注意我在这里使用 Lombok @Data 来声明 getter/setter。
import com.pls.core.jpa.nativequery.NativeQueryResultEntity;
import lombok.Data;
@Data
@NativeQueryResultEntity
public class FieldsDTO{
@NativeQueryResultColumn(index = 0)
private String fieldA;
@NativeQueryResultColumn(index = 1)
private String fieldB;
@NativeQueryResultColumn(index = 2)
private String fieldC;
}
然后使用 NativeQueryResultsMapper
String queryStr = "select field_a, field_b, field_c from db.table"
Query query = entityManager.createNativeQuery(queryStr);
List result = NativeQueryResultsMapper.map(query.getResultList(), FieldsDTO.class);
这就是你应该做的。 result
将是 FieldsDTO
个对象的列表。
答案 5 :(得分:-2)
如果你提供了一个合适的构造函数,Hibernate将填充任何pojo。
select new Pojo(p1, p2, p3,...) from entity)
将返回Pojo实例列表。
答案 6 :(得分:-3)
我在这个问题上苦苦挣扎,最后找到了一个很好的解决方案。
情况:我有一个本机查询,我只从数据库表中获取少数字段或所有字段,或者当我从表中获取数据时,我也可以对列进行一些操作。
现在我想将使用getResultList()方法得到的本地查询的输出映射到自己的POJO类/非JPA类中。 getResultList()的输出是一个对象列表,即List,因此我们需要手动循环并将值设置到我们的bean / pojo类中。查看下面的代码段。
所以我的查询就是这个 -
// This is your POJO/bean class where you have settter/getter
// methods of values you want to fetch from the database
List<YourPOJO> yourPOJOList = new ArrayList<YourPOJO>();
YourPOJO pojo = null;
StringBuffer SQL = new StringBuffer();
// I am creating some random SQL query
SQL.append("SELECT tb1.col1, ");
SQL.append(" tb1.col2, ");
SQL.append(" tb2.col3, ");
SQL.append("FROM Table1 tb1, Table2 tb2 ");
SQL.append("WHERE tb1.ID = tb2.ID ");
qry = getEntityManager().createNativeQuery(SQL.toString());
List<Object[]> cdList = qry.getResultList();
for(Object[] object : cdList){
pojo = new YourPojo();
// Here you manually obtain value from object and map to your pojo setters
pojo.setCode(object[0]!=null ? object[0].toString() : "");
pojo.setProductName(object[1]!=null ? object[1].toString() : "");
pojo.setSomeCode(object[2]!=null ? object[2].toString() : "");
yourPOJOList.add(pojo);
}