数据 Rest 存储库自定义注释查询
Data Rest Repository Custom Annotated Query
我正在努力完成 Spring Data-Rest 指南并努力编写自定义注释查询,但不确定是否可行,这是代码:
类别存储库
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
}
}
如果我想 select 来自两个实体的特定字段,我是否需要像上面那样具有自定义 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 ?
您的查询:
@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+'%')")
在您的自定义查询中,没有类别和库存的连接映射。通过在连接中按其 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
经过无数小时的测试,我决定将代码放在控制器中并通过 EntityManager 访问它,并且成功了。从控制器让它工作后,我意识到 JPA/Hibernate 需要一个实体而不是 Object/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
}
我不确定这是否是您的 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。
我正在努力完成 Spring Data-Rest 指南并努力编写自定义注释查询,但不确定是否可行,这是代码:
类别存储库
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
}
}
如果我想 select 来自两个实体的特定字段,我是否需要像上面那样具有自定义 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 ?
您的查询:
@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+'%')")
在您的自定义查询中,没有类别和库存的连接映射。通过在连接中按其 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
经过无数小时的测试,我决定将代码放在控制器中并通过 EntityManager 访问它,并且成功了。从控制器让它工作后,我意识到 JPA/Hibernate 需要一个实体而不是 Object/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
}
我不确定这是否是您的 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。