如何在不复制 ResourceAssembler 的情况下在 spring 数据中创建自定义本机查询?
How to create custom native query in spring data rest without duplicating their ResourceAssembler?
我有一个看起来像那样的控制器
@RestController
public class LocationsController {
@Autowired
private EntityManager manager;
private String withinQuery =
"WITH L as\n" +
"\n" +
"(SELECT *\n" +
"FROM location\n" +
"\n" +
"WHERE ST_Distance(ST_FlipCoordinates(location.shape), ST_FlipCoordinates(ST_GeomFromGeoJSON('%s'\n" +
" )))=0)\n" +
"\n" +
"SELECT *\n" +
"FROM L\n" +
"WHERE id NOT IN (\n" +
"SELECT metalocation_id FROM location\n" +
"WHERE metalocation_id IS NOT NULL\n" +
")";
private String nearestQuery =
"select * from location order by ST_Distance(ST_FlipCoordinates(location.shape), ST_FlipCoordinates(St_GeomFromGeoJSON('%s'))) limit 1";
@RequestMapping(value="near", method = RequestMethod.GET)
public List<Location> getNearestLocations(@RequestParam(value = "point") String pointAsString) throws IOException {
List<Location> locationCloseToPoint = manager.createNativeQuery(String.format(withinQuery, pointAsString), Location.class).getResultList();
if (locationCloseToPoint.size() == 0) {
List<Location> closesLocation = manager.createNativeQuery(String.format(nearestQuery, pointAsString), Location.class)
.getResultList();
locationCloseToPoint.addAll(closesLocation);
}
return locationCloseToPoint;
}
}
如您所见return 位置列表。
@Entity
public class Location {
public Geometry getShape() {
return shape;
}
public void setShape(Geometry shape) {
this.shape = shape;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private Geometry shape;
@ManyToOne(cascade = CascadeType.ALL)
private Location metalocation;
问题是我想 return 这个列表的格式 spring data rest 用于包含所有 hateoas 字段和内容的位置资源。更具体地说,我想在输出中有一个 link 到元定位。
我读过 spring-hateoas 和 ResourceAssembler 以及 @RepositoryRestController,我想我可以通过编写自定义 ResourceAssembler 来复制 spring-data-rest 正在做的事情,但我没有想要,因为你知道,为什么我要编写已经由 spring-data-rest 编写的代码,对吗?
他们自动完成所有这些组装工作,对吧?因为我在 http 输出中看到了它。所以我觉得应该有办法使用它。
您可以尝试以下方法。
首先用 @RepositoryRestController
而不是 @RestController
注释你的控制器。
然后您可以使用 spring data rest 在内部使用的资源汇编器 - PersistentEntityResourceAssembler
下面的例子适合我。
@RepositoryRestController
public class DemoController {
private final ProductRepository productRepository;
private final PagedResourcesAssembler<Object> pagedResourcesAssembler;
@Autowired
public DemoController(ProductRepository productRepository,
PagedResourcesAssembler<Object> pagedResourcesAssembler) {
this.productRepository = productRepository;
this.pagedResourcesAssembler = pagedResourcesAssembler;
}
//use PersistentEntityResourceAssembler and PagedResourcesAssembler to return a resource with paging links
@RequestMapping(method = GET, path="/products/search/listProductsPage", produces = HAL_JSON_VALUE)
public ResponseEntity<PagedResources<PersistentEntityResource>> getAllPage(Pageable pageable, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
Iterable<?> all = productRepository.findAll(pageable);
return ResponseEntity.ok(pagedResourcesAssembler.toResource((Page<Object>) all, persistentEntityResourceAssembler));
}
//return Resources of entity resources
@RequestMapping(method = GET, path="/products/search/listProducts", produces = HAL_JSON_VALUE)
public ResponseEntity<Resources<PersistentEntityResource>> getAll(Pageable pageable, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
return ResponseEntity.ok(new Resources<PersistentEntityResource>(productRepository.findAll().stream()
.map(persistentEntityResourceAssembler::toResource)
.collect(Collectors.toList())));
}
}
getAll
方法可能就是您想要的。
我还添加了 getAllPage
变体,可将 Page 转换为 PagedResource - 如果您获得集合资源,这就是 spring 数据剩余生成的内容。在这里您还必须使用 PagedResourcesAssembler 来生成页面链接。
这是您要搜索的内容吗?
在你的情况下,我也会尽量避免使用自定义控制器 - 如果你可以将你的本机查询表达为存储库查找器,spring data rest 会自动公开查找器。 Spring 数据 jpa 似乎支持通过注释进行本机查询 - http://docs.spring.io/spring-data/jpa/docs/1.9.1.RELEASE/reference/html/#jpa.query-methods.at-query
我有一个看起来像那样的控制器
@RestController
public class LocationsController {
@Autowired
private EntityManager manager;
private String withinQuery =
"WITH L as\n" +
"\n" +
"(SELECT *\n" +
"FROM location\n" +
"\n" +
"WHERE ST_Distance(ST_FlipCoordinates(location.shape), ST_FlipCoordinates(ST_GeomFromGeoJSON('%s'\n" +
" )))=0)\n" +
"\n" +
"SELECT *\n" +
"FROM L\n" +
"WHERE id NOT IN (\n" +
"SELECT metalocation_id FROM location\n" +
"WHERE metalocation_id IS NOT NULL\n" +
")";
private String nearestQuery =
"select * from location order by ST_Distance(ST_FlipCoordinates(location.shape), ST_FlipCoordinates(St_GeomFromGeoJSON('%s'))) limit 1";
@RequestMapping(value="near", method = RequestMethod.GET)
public List<Location> getNearestLocations(@RequestParam(value = "point") String pointAsString) throws IOException {
List<Location> locationCloseToPoint = manager.createNativeQuery(String.format(withinQuery, pointAsString), Location.class).getResultList();
if (locationCloseToPoint.size() == 0) {
List<Location> closesLocation = manager.createNativeQuery(String.format(nearestQuery, pointAsString), Location.class)
.getResultList();
locationCloseToPoint.addAll(closesLocation);
}
return locationCloseToPoint;
}
}
如您所见return 位置列表。
@Entity
public class Location {
public Geometry getShape() {
return shape;
}
public void setShape(Geometry shape) {
this.shape = shape;
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private Geometry shape;
@ManyToOne(cascade = CascadeType.ALL)
private Location metalocation;
问题是我想 return 这个列表的格式 spring data rest 用于包含所有 hateoas 字段和内容的位置资源。更具体地说,我想在输出中有一个 link 到元定位。
我读过 spring-hateoas 和 ResourceAssembler 以及 @RepositoryRestController,我想我可以通过编写自定义 ResourceAssembler 来复制 spring-data-rest 正在做的事情,但我没有想要,因为你知道,为什么我要编写已经由 spring-data-rest 编写的代码,对吗?
他们自动完成所有这些组装工作,对吧?因为我在 http 输出中看到了它。所以我觉得应该有办法使用它。
您可以尝试以下方法。
首先用 @RepositoryRestController
而不是 @RestController
注释你的控制器。
然后您可以使用 spring data rest 在内部使用的资源汇编器 - PersistentEntityResourceAssembler
下面的例子适合我。
@RepositoryRestController
public class DemoController {
private final ProductRepository productRepository;
private final PagedResourcesAssembler<Object> pagedResourcesAssembler;
@Autowired
public DemoController(ProductRepository productRepository,
PagedResourcesAssembler<Object> pagedResourcesAssembler) {
this.productRepository = productRepository;
this.pagedResourcesAssembler = pagedResourcesAssembler;
}
//use PersistentEntityResourceAssembler and PagedResourcesAssembler to return a resource with paging links
@RequestMapping(method = GET, path="/products/search/listProductsPage", produces = HAL_JSON_VALUE)
public ResponseEntity<PagedResources<PersistentEntityResource>> getAllPage(Pageable pageable, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
Iterable<?> all = productRepository.findAll(pageable);
return ResponseEntity.ok(pagedResourcesAssembler.toResource((Page<Object>) all, persistentEntityResourceAssembler));
}
//return Resources of entity resources
@RequestMapping(method = GET, path="/products/search/listProducts", produces = HAL_JSON_VALUE)
public ResponseEntity<Resources<PersistentEntityResource>> getAll(Pageable pageable, PersistentEntityResourceAssembler persistentEntityResourceAssembler) {
return ResponseEntity.ok(new Resources<PersistentEntityResource>(productRepository.findAll().stream()
.map(persistentEntityResourceAssembler::toResource)
.collect(Collectors.toList())));
}
}
getAll
方法可能就是您想要的。
我还添加了 getAllPage
变体,可将 Page 转换为 PagedResource - 如果您获得集合资源,这就是 spring 数据剩余生成的内容。在这里您还必须使用 PagedResourcesAssembler 来生成页面链接。
这是您要搜索的内容吗?
在你的情况下,我也会尽量避免使用自定义控制器 - 如果你可以将你的本机查询表达为存储库查找器,spring data rest 会自动公开查找器。 Spring 数据 jpa 似乎支持通过注释进行本机查询 - http://docs.spring.io/spring-data/jpa/docs/1.9.1.RELEASE/reference/html/#jpa.query-methods.at-query