Как вызвать пользовательскую функцию Oracle, возвращающую значение из JPA - PullRequest
4 голосов
/ 09 августа 2011

У меня есть пользовательская функция в Oracle, возвращающая число после удаления записей. Я мог бы получить значение в sql_plus, например

call my_function(4) into :out_number;

где out_number - переменная, определенная как число.

Я могу проверить, что out_number имеет значение, когда я делаю "PRINT OUT_NUMBER."

У меня вопрос, как вызвать эту функцию из JPA.

Я пробовал как

Query query = em.createNativeQuery("{call my_function(?)}");
query.serParameter(1, 4);
return query.executeUpdate();

и получил ошибку, в основном my_function не определена. Как я могу получить возвращаемое значение как в CALL ... INTO для SQL_PLUS?

Если этот метод нежелателен, может кто-нибудь порекомендовать какие-либо предложения? JPA - единственный вариант для меня в данный момент. Я мог бы создать хранимую процедуру, но я не уверен, смогу ли я получить возвращаемое значение из нее, поскольку параметры OUT не поддерживаются.

Заранее спасибо за помощь!

Ответы [ 5 ]

2 голосов
/ 09 августа 2011

Я использовал это для выполнения собственных функций в oracle:

Query query = em.createNativeQuery("select my_function(:param) from dual");
query.setParameter("param", 4);
return query.getSingleResult();
1 голос
/ 14 октября 2016

С https://vladmihalcea.com/how-to-call-oracle-stored-procedures-and-functions-from-hibernate/:

Во-первых, мы можем просто вызвать функцию Oracle, как и любой другой запрос SQL:

BigDecimal commentCount = (BigDecimal) entityManager
    .createNativeQuery(
        "SELECT fn_count_comments(:postId) FROM DUAL"
    )
    .setParameter("postId", 1L)
    .getSingleResult();

Другой подход заключается в вызове функции базы данных с использованием простого API JDBC:

Session session = entityManager.unwrap( Session.class );

final AtomicReference<Integer> commentCount = 
    new AtomicReference<>();

session.doWork( connection -> {
    try (CallableStatement function = connection
            .prepareCall(
                "{ ? = call fn_count_comments(?) }"
            )
        ) {
        function.registerOutParameter( 1, Types.INTEGER );
        function.setInt( 2, 1 );
        function.execute();
        commentCount.set( function.getInt( 1 ) );
    }
} );
1 голос
/ 12 декабря 2012

Это довольно старый вопрос, но я не нашел здесь правильного решения ... Вот код, который работает в моем проекте:

    EntityManager em;
    String functionName = "NameOfStoredFunction";
    Map<String, Object> arguments = new LinkedHashMap();
    arguments.put("nameOfArgument", "value");
    StoredFunctionCall functionCall = new StoredFunctionCall();
    functionCall.setProcedureName(functionName);
    functionCall.setResult("RESULT", String.class);

    for(String key : arguments.keySet()){
        functionCall.addNamedArgumentValue(key, arguments.get(key));
    }

    ValueReadQuery valQuery = new ValueReadQuery();
    valQuery.setCall(functionCall);

    Query query = ((JpaEntityManager)em.getDelegate()).createQuery(valQuery);

    String call_result = (String)query.getSingleResult();
0 голосов
/ 21 января 2019

При использовании Spring Data JPA / Spring JDBC вы можете использовать SimpleJdbcCall для вызова функций и процедур.

Для такого заголовка функции:

FUNCTION get_text (p_param IN VARCHAR2) RETURN VARCHAR2

Использовать этот вызов:

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 MyRepository {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public String callGetTextFunction(String param) {
        SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withCatalogName("PKG_PACKAGE") //package name
                .withFunctionName("GET_TEXT"); //function name
        SqlParameterSource paramMap = new MapSqlParameterSource()
                .addValue("p_param", param));
        //First parameter is function output parameter type.
        return jdbcCall.executeFunction(String.class, paramMap));
    }

}
0 голосов
/ 10 августа 2011

Если вы используете EclipseLink, вы можете использовать объект StoredFunctionCall для вызова хранимой функции, такой как эта.

Вы также можете определить его как именованный запрос, используя @ NamedStoredFunctionQuery.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...