如何在jparepository中创建自定义查询但返回实体以外的对象?

时间:2015-01-15 17:43:59

标签: rest repository spring-data-jpa

我们有一个名为Location的项目,并且已经成功实现了jparepositories,定义了几种搜索方法。我们希望有一个额外的搜索方法可以返回一组街道名称(从位置表中提取)而不是一组位置 - 因此我们可以在用户在街道中键入时实现自动完成。首先我们尝试了@Query注释:

 @RepositoryRestResource(collectionResourceRel = "locations", path = "locations")
 public interface LocationRepository extends JpaRepository<Location, Integer>, LocationRepositoryCustom {
    List<Location> findByStreetNameStartingWithIgnoreCase(@Param("street") String streetName);

    @Modifying
    @Query("select x.streetName from Location x where x.streetName like :street%")
    List<String> findStreetNameStartingWith(@Param("street") String streetName);
 }

如果我查询了一条不存在的街道的程序(例如,没有以X开头的街道),我会返回一个空集{}。如果我查询确实存在的街道(街道= Br,因为百老汇存在于数据库中),我得到了

 {"cause":null,"message":"PersistentEntity must not be null!"}

然后我们尝试使用以下方法将其实现为自定义查询:

 public interface LocationRepositoryCustom {
    @Query("select x.streetName from Location x where x.streetName like :streetName")
    public List<String> collectStreetNames(@Param("streetName") String streetName);
 }

 class LocationRepositoryImpl implements LocationRepositoryCustom {

   @PersistenceContext
   private EntityManager em;

   @Override
   public List<String> collectStreetNames(String streetName) {
    List<String> retList = new ArrayList<String>();
    retList.add("start");
    retList.add("end");
    return retList;
   }
 }

这也给了我们&#34; PersistentEntity不能为空&#34;错误。实现中的代码用于返回硬代码结果,因此我们没有试图弄清楚我们的SQL是错还是我们的架构。我们在调试下运行它并验证确实返回了两个项目的列表。

问题似乎是从存储库返回除List之外的任何内容。这是对这种架构的限制吗?或者我们做错了什么,如果我们学会秘密握手,一切都会变得笨拙?

1 个答案:

答案 0 :(得分:0)

我错过的线索是'PersistentEntity不能为空'。存储库框架想要返回已注册实体的列表 - 而不是任何旧的POJO或原语。解决方案是定义查询可以返回的实体:

@Entity
@Table(name="PString")
public class PString {

  @Column(name="Name", length=40)   
  @Id   
  private String value;

  public PString() { }
  public PString(String name) {
    this.value = name;
  }

  public String getValue() {
    return value;
  }
  public void setValue(String value) {
    this.value = value;
  }
}

除此之外,还需要一个标准的PStringRepository:

@RepositoryRestResource(collectionResourceRel = "strings", path = "strings")
public interface PStringRepository extends JpaRepository<PString, String> {
}

然后,我在LocationRepositoryCustom中的自定义函数变为:

@Override 
public List<PString> collectStreetNames(String streetName) 
{ 
    Query query = em.createNativeQuery("select distinct streetName from Location where streetName like ?"); 
    query.setParameter(1, streetName + "%"); 
    List<PString> returned = new ArrayList<PString>();

    @SuppressWarnings("unchecked")
    List<String> list = query.getResultList(); 

    for (String string : list) 
    {
        returned.add(new PString(string));
    }   

    return returned; 
}

现在返回StreetNames列表。 (它们被格式化为字符串项的hrefs,因此所有空格都替换为%20,但我可以处理它。)有趣的是注意到PString表不需要存在于数据库模式中 - 返回的hrefs实际上不会引用到数据库中的实际数据项。

请注意,这并没有回答如何使用@Query注释执行此操作的问题。我通过返回List再次尝试了,但仍然遇到了同样的错误。