提问者:小点点

如何在REST Web服务中实现最简单的异类?


我需要一个直接从存储过程返回数据的JSONendpoint。示例:

@Procedure("complex")
String complexStoredProcedure();

最简单的情况是不带参数的GETendpoint...返回的数据是一个(blabck-box) JSON,与Spring实体没有关系,也没有特殊的数据类型(对于我的Spring应用程序是一个“外来数据类型”)...

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

@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+"}";
}

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

编辑:清理了多余的代码片段,转移到下面的回答-Wiki。


共2个答案

匿名用户

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

我在oracleDB上创建了一个简单的过程:

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

要在Spring环境中使用@过程,您需要一个Entity和一个Repository。所以我创建了一个简单的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;
    }
}

结果是:

所以您不能在非存储库方法上使用< code>@Procedure注释。

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

匿名用户

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

以“https://stackoverflow.com/q/41880120/287948“上下文……而且,当我使用PostgreSQL时(SELECT f(x)有效),@QuerynativeQuery=true)是@过程的一种变通方法。。。

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

任何Spring域都可以使用任何@Query,因此域选择只是一种“内部组织”和语义,对本机SQL代码和域/存储库选择没有限制。

>

  • 在域的domain. repository包文件中,使用@Query添加一个方法,并使用其他导入添加所有查询上下文导入(QueryAnnoation、JpaRepository、query.Param等,如果需要);

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

    在Controlll的方法中,调用服务中定义的方法。

    步骤1:将新的< code>@Query添加到现有的存储库文件中,例如< code > myprj/address/domain/repository/icityrepository . Java

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

    外星人在那里!

    步骤2:导入存储库并将定义的findCustom()添加到现有的服务文件中,例如myprj/address/service/CityService.java

    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!!
    
    }
    

    Step3:将定义的cityService. findCustom()添加到现有的控制器文件中,例如。myprj/address/控制器/CityController.java…它是一个虚拟endpoint来测试和显示查询结果,

    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+"}";
        }
    }
    

    如Patrick所示,您可以将@Autowired添加到存储库中进行设置,并直接在Controller.java文件中使用repository.findCustom()