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

Rest 如何在jparepository中创建自定义查询,但返回实体以外的对象?,rest,repository,spring-data-jpa,Rest,Repository,Spring Data Jpa,我们有一个名为Location的类的项目,并且成功地实现了jparepositories,定义了几个搜索方法。我们希望有一个额外的搜索方法,它将返回一组街道名称(从位置表中提取),而不是一组位置-因此我们可以在用户在街道中键入时实现自动完成。首先,我们尝试了@Query注释: @RepositoryRestResource(collectionResourceRel = "locations", path = "locations") public interface LocationRep

我们有一个名为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);
 }
然后,我们尝试将其实现为自定义查询,使用:

 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;
   }
 }
公共接口位置RepositoryCustom{
@查询(“从位置x选择x.streetName,其中x.streetName类似:streetName”)
公共列表集合streetName(@Param(“streetName”)字符串streetName);
}
类LocationRepositoryImpl实现LocationRepositoryCustom{
@持久上下文
私人实体管理者;
@凌驾
公共列表集合streetName(字符串streetName){
List retList=new ArrayList();
添加(“开始”);
重新列出。添加(“结束”);
返回列表;
}
}
这也给了我们“PersistentEntity不得为null”错误。实现中的代码用于返回硬代码结果,因此我们没有试图找出我们的SQL是错误的还是我们的体系结构是错误的。我们在debug下运行它,并验证是否返回了两个项目的列表


问题似乎是从存储库返回列表以外的任何内容。这是对这种架构的限制吗?还是说我们做错了什么,如果我们学会了秘密握手,一切都会好起来?

我错过的线索是“持久性不能为空”。存储库框架希望返回已注册实体的列表,而不是任何旧的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> {
}
@RepositoryRestResource(collectionResourceRel=“strings”,path=“strings”)
公共接口PStringRepository扩展了JpaRepository{
}
然后,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; 
}
@覆盖
公共列表集合streetName(字符串streetName)
{ 
Query Query=em.createNativeQuery(“从streetName类似的位置选择不同的streetName?”);
query.setParameter(1,streetName+“%”);
返回的列表=新的ArrayList();
@抑制警告(“未选中”)
List=query.getResultList();
用于(字符串:列表)
{
返回.add(新的PString(字符串));
}   
返回;
}
现在返回街道名称列表。(它们被格式化为字符串项的HREF,因此所有空格都替换为%20,但我可以处理它。)有趣的是,PString表不需要存在于数据库架构中-返回的HREF实际上并不引用数据库中的实际数据项


请注意,这并没有回答如何使用@Query注释执行此操作的问题。我再次尝试返回列表,但仍然出现相同的错误。

这种方法对我来说不太有效,您找到解决方案了吗?如果是,您能在这里回答:
@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; 
}