【问题标题】:Data Rest Repository Custom Annotated QueryData Rest Repository 自定义注释查询
【发布时间】:2015-11-10 15:47:26
【问题描述】:

我正在阅读 Spring Data-Rest 指南并努力编写自定义带注释的查询,但不确定是否可行,代码如下:

CategoryRepository

package com.example.repositories

import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.data.rest.core.annotation.RepositoryRestResource
import org.springframework.data.rest.core.annotation.RestResource

import com.example.entities.Category
import com.example.entities.InventoryDetail

@RepositoryRestResource(collectionResourceRel="categories", path="categories")
interface CategoryRepository extends JpaRepository<Category, Long> {

    @RestResource(path="inventoryByCategory",rel="inventoryByCategory")
    @Query("select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where upper(c.name) like upper(:name+'%')")
    Page<InventoryDetail> queryByCategoryStartsWithIgnoreCase(@Param("name") String name, Pageable pageable)

}

上面的查询是我正在努力解决的问题,不知道如何正确执行此操作。我搜索了几个小时寻找解决方案,但找不到。

类别实体

package com.example.entities

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.JoinColumn
import javax.persistence.OneToMany
import javax.persistence.Table

@Entity
@Table(name="categories")
class Category implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    long id

    @Column
    String name

    @Column
    String description

    @OneToMany(targetEntity=Inventory.class, fetch=FetchType.LAZY)
    @JoinColumn(name="category")
    List<Inventory> inventory

}

库存实体

package com.example.entities

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.Index
import javax.persistence.Table

@Entity
@Table(name="inventory", indexes=[ @Index(columnList="category", unique=false) ])
class Inventory implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    long id

    @Column
    long category

    @Column
    String item

    @Column
    String description

    @Column
    long price

    @Column
    long onHand
}

库存详情

package com.example.entities

import javax.persistence.Column;

class InventoryDetail {

    long id

    String item

    String name

    InventoryDetail(long id, String item, String name) {
        this.id = id
        this.item = item
        this.name = name
    }

}

如果我想从两个实体中选择特定字段,我是否需要像上面的那样有一个自定义 DTO?是否可以只使用new map(...)?无论哪种方式,查询都会运行并且我在控制台中看到它,但是在 HAL 浏览器中它给了我一个 500 错误,我确定我忽略了某些东西,但不确定它是什么。

提前感谢您的帮助!

编辑

这是 Hibernate 查询的输出:

Hibernate: select count(category0_.id) as col_0_0_ from categories category0_ inner join inventory inventory1_ on category0_.id=inventory1_.category where upper(category0_.name) like upper(?+'%')
Hibernate: select inventory1_.id as col_0_0_, inventory1_.item as col_1_0_, category0_.name as col_2_0_ from categories category0_ inner join inventory inventory1_ on category0_.id=inventory1_.category where upper(category0_.name) like upper(?+'%') limit ?

【问题讨论】:

  • 内部联接仅从类别和库存中选择常用数据。如果您需要基于类别的库存,请使用左连接;如果您需要基于库存的类别,请使用右连接。
  • 我左右都试过了,都不适合我。
  • 当我从终端中的 curl 请求时,它根本不返回任何内容。当我从 HAL 浏览器运行它时,它返回 500 Internal Server Error,并且在 STS 控制台中没有错误。
  • 请检查其他简单查询是否有效?
  • 好的,我在您的查询中遇到了问题,请检查此查询:select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where c.id= i.category and upper(c.name) like upper(:name+'%')

标签: spring jpa spring-data-rest


【解决方案1】:

经过无数小时的测试,我决定将代码放入控制器中并通过 EntityManager 访问它,它成功了。从控制器开始工作后,我意识到 JPA/Hibernate 期望的是实体而不是对象/DTO。

我能够做到这一点......

List<Object> list(String name) {
    def qry = "select new map(i.id as id, i.item as item, c.name as category) from Category c join c.inventory i where upper(c.name) like upper(:name+'%')"
    List<Object> results = em.createQuery(qry).setParameter('name',name).getResultList()
    return results
}

【讨论】:

    【解决方案2】:

    您的查询:

    @Query("select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where upper(c.name) like upper(:name+'%')")
    

    在您的自定义查询中,类别和库存没有连接映射。通过以下方式替换这行代码:Category 和 Inventory 在 join 中由它们的 id 映射:

     @Query("select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where c.id=i.category upper(c.name) like upper(:name+'%')")
    

    注意:jpql 默认join 表示inner join

    【讨论】:

    • 如果您查看我粘贴在问题中的休眠查询,连接映射会自动出现。通过在实体中定义它,我不必在查询中定义它。没用,我试过了。
    • 请在Category,Inventory,InventoryDetail类中添加访问修饰符public,然后检查。
    【解决方案3】:

    我不确定这是否是您的 500 错误的原因,但我发现您的查询有问题,尤其是您如何将参数 name 与通配符 % 连接起来。

    @Query("select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where upper(c.name) like upper(:name+'%')")
    

    您必须删除加号和单引号。

    @Query("select new com.example.entities.InventoryDetail(i.id, i.item, c.name) from Category c join c.inventory i where upper(c.name) like upper(:name%)")
    

    查看示例实现here

    【讨论】:

    • 我在大部分项目中都使用 Groovy,我没有从中得到错误。该错误是由于我没有返回 JPA/Hibernate 所期望的 Entity
    猜你喜欢
    • 2015-03-25
    • 2014-11-16
    • 2019-12-23
    • 2018-06-17
    • 2016-05-07
    • 2014-11-27
    • 1970-01-01
    • 2020-04-12
    • 2019-03-08
    相关资源
    最近更新 更多