【问题标题】:Spring Data JPA calling Oracle FunctionSpring Data JPA 调用 Oracle 函数
【发布时间】:2018-02-02 16:11:23
【问题描述】:

我正在运行一个简单的应用程序,它使用 Spring Boot + Spring Data JPA 进行持久化。

下面是一个示例 Oracle 函数,我希望在 Service 实现类中返回值。

CREATE OR REPLACE PACKAGE PKG_TEST AS 
  FUNCTION HELLO_WORLD(TEXT VARCHAR2) RETURN VARCHAR2;
END PKG_TEST;

CREATE OR REPLACE PACKAGE BODY PKG_TEST AS 
  FUNCTION HELLO_WORLD(TEXT VARCHAR2) RETURN VARCHAR2 IS
  BEGIN
    RETURN 'HELLO WORLD ' || TEXT;
  END;
END PKG_TEST;

在没有框架的情况下这样做会很简单,但是项目是内置在 Spring Boot JPA 中的,所以最好使用它。

我需要一个参考指南链接或简单的基本结构。 我搜索了整个 SO 和 Spring Data JPA 参考,我找到的所有示例都是针对 CRUD 和存储过程的,没有针对函数的。

我尝试使用为函数修改的存储过程示例,但没有成功。

【问题讨论】:

  • 我认为不支持sql函数,据我所知有调用它们的方法,但没有创建和存储它们。 JPA 规范没有来自 javadoc 的此类合同,我怀疑它是否由任何持久性提供程序实现

标签: java spring oracle function jpa


【解决方案1】:
【解决方案2】:

如果您使用 Hibernate 作为 JPA 提供程序,您可以创建自定义方言并注册所需的功能。

public class CustomDialect extends Oracle10gDialect {
    public CustomDialect() {
        super();
        // CustomFunction implements SqlFunction
        registerFunction("custom_function", new CustomFunction());
        // or use StandardSQLFunction; useful for coalesce
        registerFunction("coalesce", new StandardSQLFunction("coalesce"));
    }
}

【讨论】:

    【解决方案3】:

    您可以通过本机查询调用您的函数并从双重查询中获取结果。

    public interface HelloWorldRepository extends JpaRepository<HelloWorld, Long> {
    
        @Query(nativeQuery = true, value = "SELECT PKG_TEST.HELLO_WORLD(:text) FROM dual")
        String callHelloWorld(@Param("text") String text);
    
    }
    

    请注意,如果您的函数使用 DML 语句,它将不起作用。在这种情况下,您需要在查询上使用@Modyfing 注释,但是由于@Modyfing 返回类型的限制,函数本身必须返回数字。

    您也可以实现您的CustomRepository 并使用SimpleJdbcCall

    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
    import org.springframework.jdbc.core.namedparam.SqlParameterSource;
    import org.springframework.jdbc.core.simple.SimpleJdbcCall;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public class HelloWorldRepositoryImpl implements HelloWorldRepositoryCustom {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Override
        public String callHelloWorld() {
            SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                    .withCatalogName("PKG_TEST") //package name
                    .withFunctionName("HELLO_WORLD");
            SqlParameterSource paramMap = new MapSqlParameterSource()
                    .addValue("param", "value"));
            //First parameter is function output parameter type.
            return jdbcCall.executeFunction(String.class, paramMap));
        }
    
    }
    

    【讨论】:

      【解决方案4】:
      public interface inteface-name extends CrudRepository<Object,Long> {
      
          @Procedure(procedureName = "procedure-name", outputParameterName = "param-out-name")
          BigDecimal method-name(dataType input-param);
      }
      

      【讨论】:

        【解决方案5】:

        如果您需要从函数返回一组列,其中 n 行作为 oracle 类型返回,请使用 Table(function_name) 和 select 语句将类型解析为表和获取对象数组 List 的列表。

        @Query(nativeQuery = true, value = "SELECT * FROM TABLE(ListOfStates(:country))")
        List<Object[]> findStatesByCountry(@Param("country") String country);
        

        【讨论】:

          【解决方案6】:
           this.entityManager.getSession().doWork(connection -> {
                  try (CallableStatement query = connection
                          .prepareCall("BEGIN ? := FUNCTION_NAME(?); END;")) {
                      query.registerOutParameter("PARAM1", Types.VARCHAR); // out param
                      query.setString("PARAM2"), "SOME_VALUE"); // in param
                      query.execute();
                      String value = query.getString("PARAM1"); //outparam result
                      System.out.println(value);
                  } catch (Exception ex) {
                     //process exception here
                  }
              });
          

          【讨论】:

            猜你喜欢
            • 2019-06-05
            • 1970-01-01
            • 2019-02-10
            • 2021-03-13
            • 2011-08-06
            • 2019-05-25
            • 1970-01-01
            • 2019-02-03
            • 2022-01-12
            相关资源
            最近更新 更多