在不创建实体的情况下使用本机查询公开端点

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 中看到它。

另外,我觉得一定有更好的方法来做到这一点。我想学习。


我想帮助:

提前致谢!

我试过你放在这里的第一个例子,它对我有用。但是有一点变化。我用过PersistenceContext.

给return一个Link作为回应我用了Link of WebMvcLinkBuilder.

解决方案
在下面的示例中,我在 PostgresSQL 中使用了两个表 EmployeeAddress。两者都有 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));
}

几个可能有帮助的例子。 link1link2
注意:我没有在我的代码库中创建任何实体 类。

尝试更改您的 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;
}

https://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.customizing-json-output.representation-model-processor