@Query返回Object而不是实体

时间:2014-04-17 01:05:25

标签: java-ee jpa spring-data

当我在选择字段中使用@Query注释时,我没有得到实体对象。如何获取实体对象?

public interface CreditCenterRepository extends JpaRepository<CreditCenter, Long> {
    @Query("SELECT CC.id, CC.loanId, CC.clientId FROM CreditCenter CC")
    List<CreditCenter> findAllIds();
}

当我从我的控制器调用此方法时,它不会抛出任何错误,但是,当我尝试迭代它时抛出classcastexception

List<CreditCenter> objects = findAllIds();
for (CreditCenter cc : objects) { //This line throws ClassCastException
    //some logic
}

2 个答案:

答案 0 :(得分:9)

好吧您似乎正在使用实体CreditCenter上的投影

@Query("SELECT CC.id, CC.loanId, CC.clientId FROM CreditCenter CC")

我的第一个想法是:  为什么你不使用这样的东西。

 @Query("SELECT CC FROM CreditCenter CC")

将返回实体列表,但是您可能不希望返回所有字段,因此我的第二个建议是使用此查询。

@Query("SELECT new package.to.CreditCenter(CC.id, CC.loanId, CC.clientId) FROM CreditCenter CC")

并在Creditcenter中添加一个支持参数顺序和类型的构造函数。这将使用JPQL和jpa repos使用它应该工作。

public class CreditCenter {

 //Member vars
 public CreditCenter (int id, int loadid, int clientid){...}
}

答案 1 :(得分:1)

如果要选择性地返回实体的某些部分,在JPA中这样做的推荐方法是专用的DTO类型,也称为投影类。对于这个特定的查询,你可以继续这样的事情:

class CreditCenterExcerpt {

  private int id, loanId, clientId;

  public CreditCenterExcerpt(int id, int loadid, int clientid) { … }
}

然后以与one described by Koitoer类似的方式使用它。

interface CrediCenterRepository implements Repository<CreditCenter, Integer> {

  @Query("select new ….CreditCenterExcerpt(CC.id, CC.loanId, CC.clientId) from CreditCenter CC")
  List<CreditCenterExcerpt> yourSpecialQueryMethod();
}

我把它作为一个单独的答案写下来的原因是使用实体类型本身有很多缺点(因此首先建议使用单独的类型):

根据定义,从预测查询执行返回的实例是分离的,无论EntityManager是否仍然打开。通过为这些调用使用单独的类型,您不会意外地创建返回的对象是完全填充和管理的实体实例的印象。

不知道投影的开发人员可能只使用返回的实例,尝试访问未填充的属性,甚至尝试依次保存实例,从而消除所有未加载的属性。