【问题标题】:How does one create a custom query in jparepository but return an object other than the entity?如何在 jparepository 中创建自定义查询但返回实体以外的对象?
【发布时间】:2015-03-14 05:09:46
【问题描述】:

我们有一个名为 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 开头的街道),我得到一个空集 {} 返回。如果我查询确实存在的街道(street=Br,因为数据库中存在百老汇),我得到 ​​p>

 {"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;
   }
 }

这也给了我们“PersistentEntity 不能为空”的错误。实现中的代码用于返回硬编码结果,因此我们不会试图确定我们的 SQL 是否错误或我们的架构。我们在调试下运行它并验证确实返回了两个项目的列表。

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

【问题讨论】:

    标签: rest repository spring-data-jpa


    【解决方案1】:

    我错过的线索是“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 列表。 (它们被格式化为字符串项的 href,因此所有空格都替换为 %20,但我可以处理。)有趣的是,PString 表不需要存在于数据库模式中 - 返回的 href 实际上并不引用到数据库中的实际数据项。

    请注意,这并不能回答如何使用 @Query 注释来解决问题。我通过返回 List 再次尝试,但仍然出现相同的错误。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-16
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 2021-11-26
    • 1970-01-01
    • 2019-07-13
    相关资源
    最近更新 更多