当前位置: 首页 > 知识库问答 >
问题:

使用本机查询公开endpoint,而不创建实体

唐兴思
2023-03-14

我想运行一些本机查询,并通过endpoint公开结果,但我想这样做,而不必创建所有实体。我只希望从数据库中获得的数据在出现时公开。

我在网站上找到了一些建议:创建没有实体的spring存储库

然而,我没能让它们工作。我对Spring很陌生。

我试过Maciej Kowalski的解决方案如下:

接口:

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();
    }
}

然而,没有暴露endpoint,就像扩展CrudRepository时发生的那样。我应该用CustomNativeRepositoryImpl做些其他事情吗?我不知道如何继续。

我还尝试了Gagarwa的解决方案:

RootEntity:

@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();
    
}

endpointhttp://localhost:8080/rootEntities被公开,但当我访问它时,我得到了一个例外:“关系根实体不存在”。因此,我在数据库中创建了表:

create table root_entity(
    id SERIAL PRIMARY KEY
)

之后,endpoint工作,并返回一个空数组(数据库中的表root_实体为空)。

我试图访问endpoint:http://localhost:8080/rootEntities/search/findFromCustomQuery,但我遇到了一个异常(找不到类型类的PersistentEntity)。

再次,我无法使它工作。

经过多次尝试,我在以下方面取得了一些进展:

@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并查看查询结果。

但是,endpoint没有出现在http://localhost:8080/中显示的endpoint列表中。我必须在浏览器中手动键入它。我希望endpoint公开以便在Swagger中看到它。

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

我想帮忙:

  • 获取一个有效的解决方案并公开endpoint

提前感谢!

共有2个答案

国俊艾
2023-03-14

我尝试了你放在这里的第一个例子,它对我很有效。但是有一点变化。我使用了持久性上下文。

为了返回一个链接作为响应,我使用了WebMvcLinkBuilder的Link

解决方案
在下面的示例中,我在postgresql中使用了两个表EmployeeAddress。两者都有区域代码

界面

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));
}

没有几个例子可能会有所帮助。链接1  link2
注意:我没有在代码库中创建任何实体类。

越琦
2023-03-14

尝试更改CustomQueryController以实现RepresentationModelProcessor

public class CustomQueryController implements RepresentationModelProcessor<RepresentationModel<RepositoryLinksResource>> {

并实现过程方法:

@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

 类似资料:
  • 我在当前项目中使用QueryDSL,在一个实例中,由于jpql的限制,我需要使用本机查询而不是jpa查询。 值得庆幸的是,通过从切换到可以很容易地从一个实体切换到另一个实体并保留api抽象层,但是在我这样做之后,实体不再映射为结果类型。 示例: 使用: 将生成适当的实体作为结果类型: 但是 有没有办法强制返回实体而不手动映射它们? 使用query_dsl_version=4.2.1的Im TLDR

  • 嗨,我正在使用svg绘制线条,但我的问题是,我正在使用公共URL绘制线条`varsvgnode=document.createElementNs('http://www.w3.org/2000/svg','svg'); 如何在不使用公共URL的情况下实现相同的功能

  • 使用endpointDSL然后用ProducerTemplate引用endpoint的正确方法是什么?当创建路由并使用endpointDSL时,Camel似乎是在为endpoint创建不同的uri。我的EndpointRouteBuilder类:

  • 我正在使用JPA的Hibernate实现(Hibernate版本:4.2.1,JPA版本:1.8.1)。我有一些本机查询,其结果映射到我的自定义POJO列表(标记为@Entity)。但是,当查询执行时,我会得到一个在我的MySQL模式中创建的空表,该表具有POJO中的属性。考虑到如果不将本机查询结果标记为“实体”,就不可能将其映射到POJO,我如何确保没有表添加到现有模式中。

  • 我设置了文件,如下所示: 当我在项目目录中运行时,将在中创建一个名为的Jar文件。其结构如下: 在执行任务时,我希望包含已编译的文件,而不是文件。我可以改变什么来实现这一点? Gradle现在给我的输出是: