在不创建实体的情况下使用本机查询公开端点
Expose endpoint with native query without creating entity
我想 运行 一些本机查询并通过端点公开结果,但我想这样做而不必创建所有实体。我只是想让从数据库中获取的数据来时暴露。
我在以下位置找到了一些建议:Create spring repository without entity
但是,我无法让它们工作。我是 Spring.
的新手
我试过 Maciej Kowalski's solution 这样的:
接口:
public interface CustomNativeRepository {
Object runNativeQuery();
}
执行:
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
@Autowired
private EntityManager entityManager;
@Override
public Object runNativeQuery() {
return entityManager.createNativeQuery(
"""
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9
"""
)
.getResultList();
}
}
但是,没有暴露端点,就像扩展 CrudRepository 时发生的那样。我应该用 CustomNativeRepositoryImpl 做些别的事情吗?我不知道如何进行。
我也试过了Gagarwa's solution:
根实体:
@Entity
public class RootEntity {
@Id
private Integer id;
}
RootEntityRepository:
@Repository
public interface RootEntityRepository extends JpaRepository<RootEntity, Integer> {
@Query(value = """
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9""",
nativeQuery = true)
public Collection<Object> findFromCustomQuery();
}
端点http://localhost:8080/rootEntities
被暴露了,但是当我访问它时,我得到了异常:"Relation root_entity does not exist"
。所以,我在数据库中创建了 table:
create table root_entity(
id SERIAL PRIMARY KEY
)
之后,端点工作,并返回一个空数组(数据库中的table root_entity为空)。
我试图访问端点:http://localhost:8080/rootEntities/search/findFromCustomQuery
,但出现异常 (Couldn't find PersistentEntity for type class
)。
同样,我无法让它工作。
经过大量尝试,我在以下方面取得了一些进展:
@RestController
public class CustomQueryController {
@Autowired
private EntityManager entityManager;
@GetMapping("/myEndpoint")
@ResponseBody
public Object runNativeQuery() {
return ResponseEntity
.ok()
.body(
entityManager.createNativeQuery(
"""
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9
"""
).getResultList()
);
}
}
使用上面的代码,我可以访问 http://localhost:8080/myEndpoint
并查看查询结果。
但是,端点未出现在 http://localhost:8080/
中显示的端点列表中。我不得不在浏览器中手动输入它。我希望公开端点以便在 Swagger 中看到它。
另外,我觉得一定有更好的方法来做到这一点。我想学习。
我想帮助:
- 获取有效并公开端点的解决方案。
- 了解我做错了什么以及如何实施 Kowalski's and Gagarwa's 解决方案。
- 能够公开最后一个解决方案 (CustomQueryController) 的端点。
提前致谢!
我试过你放在这里的第一个例子,它对我有用。但是有一点变化。我用过PersistenceContext.
给return一个Link作为回应我用了Link
of WebMvcLinkBuilder.
解决方案
在下面的示例中,我在 PostgresSQL
中使用了两个表 Employee
和 Address
。两者都有 area_code
的共同点。
界面
public interface CustomNativeRepository {
List<Object> runNativeQuery(Integer name);
}
存储库
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
Logger logger = LoggerFactory.getLogger(this.getClass());
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Object> runNativeQuery(Integer areaCode) {
Query query = entityManager.createNativeQuery(
"Select e.first_name as name from employees e where e.area_code = ? "
+ "union all " +
"Select a.address as address from address a where a.area_code = ?");
query.setParameter(1, areaCode);
query.setParameter(2, areaCode);
List<Object> response = query.getResultList();
logger.info("Response from database: {}", response);
return response;
}
}
RestEndpoint 层
@GetMapping(path ="/employee/{areaCode}")
public ResponseEntity<?> getEmployeeByCode(@PathVariable(value = "areaCode") Integer areaCode) throws NoSuchMethodException {
List<Object> response = customCustomerRepository.runNativeQuery(areaCode);
Link link = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getEmployeeByCode(areaCode)).withSelfRel();
return ResponseEntity.ok().body(CollectionModel.of(response, link));
}
尝试更改您的 CustomQueryController
以实施 RepresentationModelProcessor
public class CustomQueryController implements RepresentationModelProcessor<RepresentationModel<RepositoryLinksResource>> {
并通过以下方式实现 process
方法:
@Override
public RepresentationModel<RepositoryLinksResource> process(RepresentationModel<RepositoryLinksResource> model) {
if (model instanceof RepositoryLinksResource) {
model.add(Link.of( "http://localhost:8080" + "/myEndpoint", "myEndpoint"));
}
return model;
}
我想 运行 一些本机查询并通过端点公开结果,但我想这样做而不必创建所有实体。我只是想让从数据库中获取的数据来时暴露。
我在以下位置找到了一些建议:Create spring repository without entity
但是,我无法让它们工作。我是 Spring.
的新手我试过 Maciej Kowalski's solution 这样的:
接口:
public interface CustomNativeRepository {
Object runNativeQuery();
}
执行:
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
@Autowired
private EntityManager entityManager;
@Override
public Object runNativeQuery() {
return entityManager.createNativeQuery(
"""
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9
"""
)
.getResultList();
}
}
但是,没有暴露端点,就像扩展 CrudRepository 时发生的那样。我应该用 CustomNativeRepositoryImpl 做些别的事情吗?我不知道如何进行。
我也试过了Gagarwa's solution:
根实体:
@Entity
public class RootEntity {
@Id
private Integer id;
}
RootEntityRepository:
@Repository
public interface RootEntityRepository extends JpaRepository<RootEntity, Integer> {
@Query(value = """
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9""",
nativeQuery = true)
public Collection<Object> findFromCustomQuery();
}
端点http://localhost:8080/rootEntities
被暴露了,但是当我访问它时,我得到了异常:"Relation root_entity does not exist"
。所以,我在数据库中创建了 table:
create table root_entity(
id SERIAL PRIMARY KEY
)
之后,端点工作,并返回一个空数组(数据库中的table root_entity为空)。
我试图访问端点:http://localhost:8080/rootEntities/search/findFromCustomQuery
,但出现异常 (Couldn't find PersistentEntity for type class
)。
同样,我无法让它工作。
经过大量尝试,我在以下方面取得了一些进展:
@RestController
public class CustomQueryController {
@Autowired
private EntityManager entityManager;
@GetMapping("/myEndpoint")
@ResponseBody
public Object runNativeQuery() {
return ResponseEntity
.ok()
.body(
entityManager.createNativeQuery(
"""
SELECT 1 as col1, 2 as col2, 3 as col3
UNION ALL SELECT 4, 5, 6
UNION ALL SELECT 7, 8, 9
"""
).getResultList()
);
}
}
使用上面的代码,我可以访问 http://localhost:8080/myEndpoint
并查看查询结果。
但是,端点未出现在 http://localhost:8080/
中显示的端点列表中。我不得不在浏览器中手动输入它。我希望公开端点以便在 Swagger 中看到它。
另外,我觉得一定有更好的方法来做到这一点。我想学习。
我想帮助:
- 获取有效并公开端点的解决方案。
- 了解我做错了什么以及如何实施 Kowalski's and Gagarwa's 解决方案。
- 能够公开最后一个解决方案 (CustomQueryController) 的端点。
提前致谢!
我试过你放在这里的第一个例子,它对我有用。但是有一点变化。我用过PersistenceContext.
给return一个Link作为回应我用了Link
of WebMvcLinkBuilder.
解决方案
在下面的示例中,我在 PostgresSQL
中使用了两个表 Employee
和 Address
。两者都有 area_code
的共同点。
界面
public interface CustomNativeRepository {
List<Object> runNativeQuery(Integer name);
}
存储库
@Repository
public class CustomNativeRepositoryImpl implements CustomNativeRepository {
Logger logger = LoggerFactory.getLogger(this.getClass());
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Object> runNativeQuery(Integer areaCode) {
Query query = entityManager.createNativeQuery(
"Select e.first_name as name from employees e where e.area_code = ? "
+ "union all " +
"Select a.address as address from address a where a.area_code = ?");
query.setParameter(1, areaCode);
query.setParameter(2, areaCode);
List<Object> response = query.getResultList();
logger.info("Response from database: {}", response);
return response;
}
}
RestEndpoint 层
@GetMapping(path ="/employee/{areaCode}")
public ResponseEntity<?> getEmployeeByCode(@PathVariable(value = "areaCode") Integer areaCode) throws NoSuchMethodException {
List<Object> response = customCustomerRepository.runNativeQuery(areaCode);
Link link = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(EmployeeController.class).getEmployeeByCode(areaCode)).withSelfRel();
return ResponseEntity.ok().body(CollectionModel.of(response, link));
}
尝试更改您的 CustomQueryController
以实施 RepresentationModelProcessor
public class CustomQueryController implements RepresentationModelProcessor<RepresentationModel<RepositoryLinksResource>> {
并通过以下方式实现 process
方法:
@Override
public RepresentationModel<RepositoryLinksResource> process(RepresentationModel<RepositoryLinksResource> model) {
if (model instanceof RepositoryLinksResource) {
model.add(Link.of( "http://localhost:8080" + "/myEndpoint", "myEndpoint"));
}
return model;
}