[java] Java 및 JPA에서 저장 프로 시저를 호출하는 방법

저장 프로 시저를 호출하고 일부 데이터를 검색하는 간단한 웹 응용 프로그램을 작성 중입니다. 클라이언트의 데이터베이스와 상호 작용하는 매우 간단한 응용 프로그램입니다. 직원 ID와 회사 ID를 전달하면 저장 프로 시저가 직원 세부 정보를 반환합니다.

웹 응용 프로그램은 데이터를 업데이트 / 삭제할 수 없으며 SQL Server를 사용하고 있습니다.

Jboss AS에 웹 애플리케이션을 배포하고 있습니다. JPA를 사용하여 저장 프로 시저 또는 CallableStatement. 이 경우 JPA 사용의 장점.

또한이 저장 프로 시저를 호출하는 SQL 문은 무엇입니까? 나는 이전에 저장 프로 시저를 사용한 적이 없으며 이것으로 어려움을 겪고 있습니다. 구글은 그다지 도움이되지 않았습니다.

저장 프로시 저는 다음과 같습니다.

CREATE procedure getEmployeeDetails (@employeeId int, @companyId int)
as
begin
    select firstName, 
           lastName, 
           gender, 
           address
      from employee et
     where et.employeeId = @employeeId
       and et.companyId = @companyId
end

최신 정보:

JPA를 사용하여 저장 프로 시저를 호출하는 데 문제가있는 다른 사람을 위해 .

Query query = em.createNativeQuery("{call getEmployeeDetails(?,?)}",
                                   EmployeeDetails.class)           
                                   .setParameter(1, employeeId)
                                   .setParameter(2, companyId);

List<EmployeeDetails> result = query.getResultList();

내가 알아 차린 것 :

  1. 매개 변수 이름이 작동하지 않았으므로 매개 변수 색인을 사용해보세요.
  2. {call sp_name(?,?)}대신 올바른 SQL 문call sp_name(?,?)
  3. 저장 프로 시저가 결과 집합을 반환하는 경우 한 행만 알고 있어도 getSingleResult작동하지 않습니다.
  4. 패스 resultSetMapping이름 또는 클래스 세부 결과


답변

JPA 2.1은 이제 저장 프로 시저를 지원 합니다 . 여기 에서 Java 문서를 읽으 십시오 .

예:

StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("sales_tax");
// set parameters
storedProcedure.registerStoredProcedureParameter("subtotal", Double.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("tax", Double.class, ParameterMode.OUT);
storedProcedure.setParameter("subtotal", 1f);
// execute SP
storedProcedure.execute();
// get result
Double tax = (Double)storedProcedure.getOutputParameterValue("tax");

여기에서 자세한 예를 참조 하십시오 .


답변

Jboss AS에 웹 애플리케이션을 배포하고 있습니다. JPA를 사용하여 저장 프로 시저 또는 CallableStatement에 액세스해야합니까? 이 경우 JPA 사용의 장점.

정말 JPA 지원하지 않습니다하지만 그건 드리겠습니다 . 그래도 나는 이런 식으로 가지 않을 것입니다.

  • 일부 빈에서 저장 프로 시저 호출의 결과를 매핑하기 위해 JPA를 사용하는 것은 정말 과잉입니다.
  • 특히 JPA가 저장 프로 시저를 호출하는 데 실제로 적합하지 않다는 점을 감안할 때 (구문은 매우 장황 할 것입니다).

따라서 JDBC 데이터 액세스에 대한 Spring 지원 또는 MyBatis 와 같은 데이터 매퍼 를 사용하거나 응용 프로그램의 단순성을 고려할 때 원시 JDBC 및 CallableStatement. 사실, JDBC는 아마도 내 선택 일 것입니다. 다음은 기본적인 킥오프 예입니다.

CallableStatement cstmt = con.prepareCall("{call getEmployeeDetails(?, ?)}");
cstmt.setInt("employeeId", 123);
cstmt.setInt("companyId", 456);
ResultSet rs = cstmt.executeQuery();

참고


답변

저장 프로 시저에 매개 변수를 전달해야합니다.

다음과 같이 작동합니다.

    List result = em
      .createNativeQuery("call getEmployeeDetails(:employeeId,:companyId)")
      .setParameter("emplyoyeeId", 123L)
      .setParameter("companyId", 456L)
      .getResultList();

최신 정보:

아니면 안 될 수도 있습니다.

책에서 액션 EJB3 , 그 페이지 383에 말한다 JPA는 저장 프로 시저를 지원하지 않습니다 , 책 전체를 포함한 여러 곳에서 다운로드 할 수있는 페이지를 미리보기로, 당신은 전체 텍스트를하지 않는 것입니다 ( 이 하나 , 이것이 합법적인지 모르겠습니다).

어쨌든 텍스트는 다음과 같습니다.

JPA 및 데이터베이스 저장 프로 시저

SQL의 열렬한 팬이라면 데이터베이스 저장 프로 시저의 힘을 기꺼이 활용할 수 있습니다. 불행히도 JPA는 저장 프로 시저를 지원하지 않으므로 지속성 공급자의 독점 기능에 의존해야합니다. 그러나 네이티브 SQL 쿼리와 함께 간단한 저장 함수 (매개 변수없이)를 사용할 수 있습니다.


답변

JPA를 사용하여 저장 프로 시저 출력 매개 변수를 검색하는 방법 (2.0에는 EclipseLink 가져 오기가 필요하고 2.1에는 필요하지 않음)

이 답변은 저장 프로 시저에서 레코드 집합을 반환하는 방법에 대해 자세히 설명하지만 여기에 게시하고 있습니다. 그 이유를 알아내는 데 오랜 시간이 걸렸고이 스레드가 도움이 되었기 때문입니다.

내 응용 프로그램은 Eclipselink-2.3.1을 사용하고 있었지만 JPA 2.1은 저장 프로 시저를 훨씬 더 잘 지원하므로 Eclipselink-2.5.0으로 업그레이드하도록 강제 할 것입니다.

EclipseLink-2.3.1 / JPA-2.0 사용 : 구현 종속

이 메소드는 “org.eclipse.persistence”에서 EclipseLink 클래스를 가져와야하므로 Eclipselink 구현에 고유합니다.

http://www.yenlo.nl/en/calling-oracle-stored-procedures-from-eclipselink-with-multiple-out-parameters ” 에서 찾았습니다 .

StoredProcedureCall storedProcedureCall = new StoredProcedureCall();
storedProcedureCall.setProcedureName("mypackage.myprocedure");
storedProcedureCall.addNamedArgument("i_input_1"); // Add input argument name.
storedProcedureCall.addNamedOutputArgument("o_output_1"); // Add output parameter name.
DataReadQuery query = new DataReadQuery();
query.setCall(storedProcedureCall);
query.addArgument("i_input_1"); // Add input argument names (again);
List<Object> argumentValues = new ArrayList<Object>();
argumentValues.add("valueOf_i_input_1"); // Add input argument values.
JpaEntityManager jpaEntityManager = (JpaEntityManager) getEntityManager();
Session session = jpaEntityManager.getActiveSession();
List<?> results = (List<?>) session.executeQuery(query, argumentValues);
DatabaseRecord record = (DatabaseRecord) results.get(0);
String result = String.valueOf(record.get("o_output_1")); // Get output parameter

EclipseLink-2.5.0 / JPA-2.1 사용 : 구현 독립적 (이 스레드에 이미 문서화 됨)

이 방법은 구현에 독립적입니다 (Eclipslink 가져 오기가 필요하지 않음).

StoredProcedureQuery query = getEntityManager().createStoredProcedureQuery("mypackage.myprocedure");
query.registerStoredProcedureParameter("i_input_1", String.class, ParameterMode.IN);
query.registerStoredProcedureParameter("o_output_1", String.class, ParameterMode.OUT);
query.setParameter("i_input_1", "valueOf_i_input_1");
boolean queryResult = query.execute();
String result = String.valueOf(query.getOutputParameterValue("o_output_1"));


답변

나를 위해 Oracle 11g 및 Glassfish 2.1 (Toplink)에서는 다음 만 작업했습니다.

Query query = entityManager.createNativeQuery("BEGIN PROCEDURE_NAME(); END;");
query.executeUpdate();

중괄호가있는 변형은 ORA-00900이되었습니다.


답변

EclipseLink를 사용하는 경우 @NamedStoredProcedureQuery 또는 StoreProcedureCall을 사용하여 출력 매개 변수 또는 out 커서가있는 저장 프로 시저를 포함하여 모든 저장 프로 시저를 실행할 수 있습니다. 저장된 함수 및 PLSQL 데이터 유형에 대한 지원도 사용할 수 있습니다.

http://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Stored_Procedures를 참조하십시오
.


답변

  1. 이와 같은 IN / OUT 매개 변수를 사용하는 간단한 저장 프로 시저의 경우

    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);
  2. SYS_REFCURSOROUT 매개 변수 를 사용하는 저장 프로 시저의 경우 :

    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();
  3. 다음과 같은 SQL 함수의 경우 :

    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;

    다음과 같이 부를 수 있습니다.

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

    적어도 Hibernate 4.x 및 5.x를 사용할 때 JPA StoredProcedureQuery가 SQL FUNCTIONS에서 작동하지 않기 때문 입니다.

JPA 및 Hibernate를 사용할 때 저장 프로 시저 및 함수를 호출하는 방법에 대한 자세한 내용은 다음 문서를 확인하십시오.