Как мы можем вызвать хранимую процедуру с Hibernate и JPA? - PullRequest
16 голосов
/ 24 декабря 2010

Как мы можем вызвать хранимую процедуру, используя Hibernate или JPA?

Ответы [ 8 ]

13 голосов
/ 06 января 2017

Учитывая следующую хранимую процедуру, которая просто возвращает базовое возвращаемое значение:

CREATE OR REPLACE PROCEDURE count_comments (  
   postId IN NUMBER,  
   commentCount OUT NUMBER )  
AS 
BEGIN 
    SELECT COUNT(*) INTO commentCount  
    FROM post_comment  
    WHERE post_id = postId; 
END;

Вы можете вызвать эту процедуру со стандартным JPA:

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("count_comments")
    .registerStoredProcedureParameter(1, Long.class, 
        ParameterMode.IN)
    .registerStoredProcedureParameter(2, Long.class, 
        ParameterMode.OUT)
    .setParameter(1, 1L);

query.execute();

Long commentCount = (Long) query.getOutputParameterValue(2);

Если хранимая процедура возвращает SYS_REFCURSOR:

CREATE OR REPLACE PROCEDURE post_comments ( 
   postId IN NUMBER, 
   postComments OUT SYS_REFCURSOR ) 
AS 
BEGIN
    OPEN postComments FOR
    SELECT *
    FROM post_comment 
    WHERE post_id = postId; 
END;

Вы можете назвать это так:

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("post_comments")
    .registerStoredProcedureParameter(1, Long.class, 
         ParameterMode.IN)
    .registerStoredProcedureParameter(2, Class.class, 
         ParameterMode.REF_CURSOR)
    .setParameter(1, 1L);

query.execute();

List<Object[]> postComments = query.getResultList();

Если вы хотите вызвать функцию базы данных Oracle:

CREATE OR REPLACE FUNCTION fn_count_comments ( 
    postId IN NUMBER ) 
    RETURN NUMBER 
IS
    commentCount NUMBER; 
BEGIN
    SELECT COUNT(*) INTO commentCount 
    FROM post_comment 
    WHERE post_id = postId; 
    RETURN( commentCount ); 
END;

Вы не можете использоватьStoredProcedureQuery, поскольку он не работает с Hibernate 5, поэтому его можно назвать так:

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

или с простым JDBC:

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

Integer commentCount = session.doReturningWork( connection -> {
    try (CallableStatement function = connection.prepareCall(
            "{ ? = call fn_count_comments(?) }" )) {
        function.registerOutParameter( 1, Types.INTEGER );
        function.setInt( 2, 1 );
        function.execute();
        return function.getInt( 1 );
    }
} );

Для получения более подробной информации см.следующие статьи:

2 голосов
/ 05 мая 2011

Для выполнения удаленной процедуры используйте эту конструкцию:

Отображение

<sql-query name="RP">   
    {call some_rp(:param1, :param2)}
</sql-query>

Java-код

session.getNamedQuery("RP").setInteger("param1", 1).setInteger("param2", 2).executeUpdate();
2 голосов
/ 24 декабря 2010

Вы можете сделать следующее

 Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
PreparedStatement st = session.connection().prepareStatement("{call procedureName(?, ?)}");
                st.setString(1, formatter.format(parameter1));
                st.setString(2, formatter.format(parameter2));
                st.execute();
tx.commit();

Пожалуйста, добавляйте обработку исключений, где это необходимо.

1 голос
/ 20 марта 2018
One way to call the stored procedure from hibernate 

Declare your store procedure inside the @NamedNativeQueries annotation

//Stock.java

@NamedNativeQueries({
    @NamedNativeQuery(
    name = "callStockStoreProcedure",
    query = "CALL GetStocks(:stockCode)",
    resultClass = Stock.class
    )
})
@Entity
@Table(name = "stock")
public class Stock implements java.io.Serializable {

Call it with getNamedQuery().

Query query = session.getNamedQuery("callStockStoreProcedure")
    .setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
    Stock stock = (Stock)result.get(i);
    System.out.println(stock.getStockCode());
}

This works
0 голосов
/ 23 февраля 2016

один подход может быть с getNamedQuery ().

Query query = session.getNamedQuery("callStockStoreProcedure")
    .setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
    Stock stock = (Stock)result.get(i);
    System.out.println(stock.getStockCode());
}

вам нужно отобразить или использовать аннотации

есть другие: источник

0 голосов
/ 19 августа 2015

Hibernate обеспечивает поддержку запросов через хранимые процедуры и функции.Скажем, например, если у нас есть следующая хранимая процедура,

CREATE OR REPLACE FUNCTION selectAllEmployments
RETURN SYS_REFCURSOR
AS
    st_cursor SYS_REFCURSOR;
BEGIN
    OPEN st_cursor FOR
 SELECT EMPLOYEE, EMPLOYER,
 STARTDATE, ENDDATE,
 REGIONCODE, EID, VALUE, CURRENCY
 FROM EMPLOYMENT;
      RETURN  st_cursor;
 END;

, которая возвращает список всех сотрудников.Хранимая процедура / функция должна возвращать набор результатов как первый выходной параметр, чтобы иметь возможность работать с Hibernate.

Чтобы использовать указанный выше запрос в Hibernate, необходимо отобразить его с помощью именованного запроса.

<sql-query name="selectAllEmployees_SP" callable="true">
    <return alias="emp" class="Employment">
        <return-property name="employee" column="EMPLOYEE"/>
        <return-property name="employer" column="EMPLOYER"/>
        <return-property name="startDate" column="STARTDATE"/>
        <return-property name="endDate" column="ENDDATE"/>
        <return-property name="regionCode" column="REGIONCODE"/>
        <return-property name="id" column="EID"/>
        <return-property name="salary">
            <return-column name="VALUE"/>
            <return-column name="CURRENCY"/>
        </return-property>
    </return>
    { ? = call selectAllEmployments() }
</sql-query>

Правила / ограничения для использования хранимых процедур:

  • Запросы к хранимым процедурам не могут быть разбиты на страницы с помощью setFirstResult () / setMaxResults ().
  • Рекомендуемая форма вызова - это стандартный SQL92: { ? = call functionName(<parameters>) } или { ? = call procedureName(<parameters>}.Собственный синтаксис вызова не поддерживается.

For Oracle the following rules apply:

  • Функция должна возвращать набор результатов.
  • Первым параметром процедуры должен быть OUT, который возвращает набор результатов.Это делается с помощью типа SYS_REFCURSOR в Oracle 9 или 10. В Oracle вам нужно определить тип REF CURSOR.Дополнительную информацию смотрите в литературе Oracle.

For Sybase or MS SQL server the following rules apply:

  • Процедура должна возвращать набор результатов.Обратите внимание, что, поскольку эти серверы могут возвращать несколько наборов результатов и количество обновлений, Hibernate будет повторять результаты и принимать первый результат, являющийся набором результатов, в качестве возвращаемого значения.Все остальное будет отброшено.
  • Если вы можете включить SET NOCOUNT ON в вашей процедуре, это, вероятно, будет более эффективным, но это не является обязательным требованием.

Source Ref.: Из официальной документации Hibernate.

0 голосов
/ 03 января 2013

Вот полное решение для вызова хранимой процедуры с параметрами Just IN ---

1) Создайте хранимую процедуру для работы с таблицей или набором таблиц:

CREATE OR REPLACE procedure insertHouseHello (
house_date in timestamp,
house_name in varchar2,
house_number in number,
house_value in float) 
is
begin
 insert into House("HOUSE_DATE","HOUSE_NAME","HOUSE_NUMBER","HOUSE_VALUE")
 values ( house_date, house_name,house_number,house_value);
 commit;
 end;

2) Выполните хранимую процедуру из подсказки SQL, чтобы проверить ввод.При вызове процедуры из Java / Hibernate также вы должны увидеть похожий результат:

exec insertHouseHello(sysdate,'one',123,104); 

3) В коде Java:

log.info("Now trying to call the Stored Procedure*****************");
Query exQuery = session.createSQLQuery("CALL " +
        "insertHouseHello(:timestmp,:hname,:hno,:hvalue)");
exQuery.setParameter("timestmp", 
        new java.sql.Timestamp(Calendar.getInstance().getTime().getTime()));
exQuery.setParameter("hname", 34);
exQuery.setParameter("hno", 212);
exQuery.setParameter("hvalue", 12);
int exRows = exQuery.executeUpdate();
log.info("Executed Rows from Stored Procedure****************"+exRows);

4) Теперь проверьте результат вТаблица, которая должна обновляться соответственно:

0 голосов
/ 24 декабря 2010

Вы должны были зайти на официальный сайт документации hibernate.В любом случае вот ссылка , которая приведет вас непосредственно к разделу хранимых процедур

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