如何在REST Web服务中实现最简单的外星人?

时间:2017-01-24 19:39:17

标签: rest stored-procedures spring-boot

我需要一个JSON 端点,它直接从stored procedure返回数据。例如:

@RequestMapping(value="/howto", method=RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@Procedure(name = "MyRandom.random")  // ?? not work
public String howto() { 
    double x = random();  // from stored-procedure call, how to do it?
    return "{\"result\":"+x+"}";
}

最简单的情况是没有参数的GET端点...返回的数据是(blabck-box)JSON,与Spring 实体无关,并且没有特殊数据 - type(一个"外来数据类型"对于我的Spring应用程序).​​..

如果您需要一个例子,假设一个简单的控制器为

templateResult

如何实施?也就是说,实现控制器方法的最简单方法(调用存储过程)?

编辑:清理冗余代码片段,转移到answer-Wiki below

2 个答案:

答案 0 :(得分:4)

我不确定我是否理解你的问题,但这是我的解决方案。

我在oracle数据库上创建了一个简单的程序:

PROCEDURE TESTPROCOUTPUT
   (param2 OUT VARCHAR2)
   IS
   GETPARAM VARCHAR2(100);
BEGIN
    param2 := 'procedure Called';
END TESTPROCOUTPUT;

要在Spring环境中使用@Procedure,您需要EntityRepository。所以我创建了一个简单的Entity及其Repository

@Entity
public class City {

    @Id
    private String cityCode;

    //...getter/setter
}

存储库:

public interface LandRepository extends CrudRepository<City, String> {

    @Procedure(name="TESTPROCOUTPUT", outputParameterName="param2")
    String TESTPROCOUTPUT();
}

重要的是方法名称与过程具有相同的名称。 (不确定它是否仅适用于oracle的情况。也可以在camelCase中我认为)

因此,在您的控制器中,您现在可以轻松地自动装配存储库(或者如果您有接口的实现,则使用此方法)。

@Controller
public class CityController {

    private CityRepository cityRepository;

    @RequestMapping(value="/howto", method=RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public String howto() { 
        String s = cityRepository.TESTPROCOUTPUT();
        return "{\"result\":" + s + "}";
    }

    public CityRepository getCityRepository () {
        return cityRepository;
    }

    @Autowired
    public void setCityRepository (CityRepository cityRepository) {
        this.cityRepository= cityRepository;
    }
}

结果是:

enter image description here

因此,您无法在非存储库方法上使用@Procedure注释。

  

用于直接在存储库方法上声明JPA 2.1存储过程映射的注释。

答案 1 :(得分:2)

我正在努力回应......对于我的观点和我的基本测试来说,这只是“最简单的”,你可以展示另一种获得赏金的解决方案。

以“https://stackoverflow.com/q/41880120/287948”上下文开头....而且,当我使用PostgreSQL(SELECT f(x)有效时),@QuerynativeQuery = true)是@Procedure ...

的解决方法

有这个问题的问题:未使用@Procedure ...在Patrick的回答之后,我看到(并编辑了这一行)您可以将@Query替换为@Procedure(以及指定的其他内容)帕特里克)这个方法是一样的!

在现有中添加“外星人@Query”的3个步骤

任何Spring 都可以使用任何@Query,因此域选择只是一种“内部组织”和语义,对本机SQL代码没有约束,{{1}选择。

  1. 在域的domain/repository包文件中,添加一个方法domain.repository和其他导入添加所有查询上下文导入(QueryAnnotation,JpaRepository,query.Param)等,如果需要);

  2. 在域的@Query包文件中,添加新的自定义“find”方法定义。

  3. 在controll的方法中,调用服务中定义的方法。

  4. 使用真实文件进行说明

    Step1 :将新的service添加到现有的存储库文件中,例如。 @Query

    myprj/address/domain/repository/ICityRepository.java

    外星人就在那里!

    Step2 :导入存储库并将已定义的package com.myprj.address.domain.repository; // old import com.myprj.address.domain.entity.City; //old // ... other project's specific (old) import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; // new import org.springframework.data.repository.query.Param; // new import org.springframework.data.jpa.repository.query.Procedure; // new @Repository public interface ICityRepository extends BaseRepository<City, Long> { //old Page<City> findByState(State state, Pageable pageable); //old // here an alien example! (simplest is a call to a constant value) @Query(nativeQuery = true, value= "SELECT 1234.5678") // NEW! Double findCustom(); } 添加到现有服务文件中,例如。 findCustom()

    myprj/address/service/CityService.java

    Step3 :将已定义的package com.myprj.address.service; // old import com.myprj.address.domain.entity.City; // ... other project's specific (old) @Service public class CityService extends BaseService<City, ICityRepository, Long> { // old @Autowired public CityService(ICityRepository repository) {super(repository);} // old public Page<City> findByState(State state, Pageable pageable) { return repository.findByState(state, pageable); } // old public Double findCustom() { return repository.findCustom(); } // NEW!! } 添加到现有的控制器文件中,例如。 cityService.findCustom() ...这是一个虚拟端点来测试和显示查询结果,

    myprj/address/controller/CityController.java

    减少到2个步骤和2个文件

    如Patrick所示,您可以将package com.myprj.address.controller; // old import com.myprj.address.service.CityService; // reuse old // ... other project's specific (old) @RestController // old @RequestMapping(value = "/zip", produces = "application/json") // old public class ZipController { // old @Autowired // old private CityService cityService; // old, so reuse it // .. many many endpoints ... OLD // NEW!! @RequestMapping(value="/dummy", method=RequestMethod.GET) @ResponseStatus(HttpStatus.OK) public String dummy() { double x = cityService.findCustom(); return "{\"success\":"+x+"}"; } } 添加到存储库进行设置,并直接在@Autowired文件中使用repository.findCustom()