복붙노트

[SPRING] Spring / Hibernate / JPA에서 PostgreSQL 함수 (저장 프로 시저)를 올바르게 호출하는 방법?

SPRING

Spring / Hibernate / JPA에서 PostgreSQL 함수 (저장 프로 시저)를 올바르게 호출하는 방법?

나는 Spring MVC 4, Hibernate, PostgreSQL 9.3을 사용하고 있으며 Postgres에서 함수 (스토어드 프로 시저)를 다음과 같이 정의했다.

CREATE OR REPLACE FUNCTION spa.create_tenant(t_name character varying)
  RETURNS void AS
  $BODY$
    BEGIN
      EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I AUTHORIZATION postgres', t_name);
    END
  $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION spa.create_tenant(character varying)
OWNER TO postgres;

이 기능을 pgAdmin 내부에서 실행하면 다음과 같이 작동합니다.

select spa.create_tenant('somename');

이제 다음과 같이 내 서비스에서이 함수를 실행하려고합니다.

@Override
@Transactional
public void createSchema(String name) {
    StoredProcedureQuery sp = em.createStoredProcedureQuery("spa.create_tenant");
    sp.registerStoredProcedureParameter("t_name", String.class, ParameterMode.IN);
    sp.setParameter("t_name", name);
    sp.execute();
}

내 방법을 실행하면 다음 오류가 발생합니다.

javax.persistence.PersistenceException: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111

나는 이것이 리턴 타입을 다음과 같이 변경했기 때문에 리턴 타입 void가 함수에 정의되어 있다고 생각합니다 :

RETURNS character varying AS

내 메소드를 다시 실행하면이 예외가 대신 발생합니다.

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: Error calling CallableStatement.getMoreResults

누구도 여기에 무슨 일이 일어나고 반환 형식으로 void가있는 경우에도 PostgreSQL의 저장 프로 시저를 제대로 호출하는 방법을 알고 있습니까?

해결법

  1. ==============================

    1.엔티티 클래스에서 select와 함께 postgresql 함수를 호출하는 것처럼 NamedNativeQuery를 정의하십시오.

    엔티티 클래스에서 select와 함께 postgresql 함수를 호출하는 것처럼 NamedNativeQuery를 정의하십시오.

    import javax.persistence.NamedNativeQueries;
    import javax.persistence.NamedNativeQuery;
    import javax.persistence.Entity;
    @NamedNativeQueries(
        value={
                // cast is used for Hibernate, to prevent No Dialect mapping for JDBC type: 1111
                @NamedNativeQuery(
                      name = "Tenant.createTenant",
                     query = "select cast(create_tenant(?) as text)"
                )
         }
    )
    @Entity
    public class Tenant
    

    최대 절전 모드는 void를 매핑 할 수 없기 때문에 임시 결과는 결과를 텍스트로 변환하는 것입니다.

    public void createSchema(String name) {
        Query query = em.createNamedQuery("Tenant.createTenant")
                .setParameter(1, name);
        query.getSingleResult();
    }
    
  2. ==============================

    2.PostgreSQL을 사용하고 있기 때문에, 이미 작성한 것처럼 SELECT에있는 함수 유형의 스토어드 프로 시저를 호출 할 수 있습니다 (그렇지 않으면, select에서만 읽도록 선언 된 함수 만 실행할 수 있습니다).

    PostgreSQL을 사용하고 있기 때문에, 이미 작성한 것처럼 SELECT에있는 함수 유형의 스토어드 프로 시저를 호출 할 수 있습니다 (그렇지 않으면, select에서만 읽도록 선언 된 함수 만 실행할 수 있습니다).

    EntityManager.createNativeQuery (SQL)를 사용할 수 있습니다.

    Spring을 사용하기 때문에 SimpleJdbcTemplate.query (SQL)를 사용하여 모든 SQL 문을 실행할 수있다.

  3. ==============================

    3.문제를 일으키는 것은 되돌아 오는 보노라고 생각합니다. 이 주제에 대한 기사도 있습니다.

    문제를 일으키는 것은 되돌아 오는 보노라고 생각합니다. 이 주제에 대한 기사도 있습니다.

    CREATE OR REPLACE FUNCTION spa.create_tenant(t_name character varying)
      RETURNS bigint AS
      $BODY$
        BEGIN
          EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I AUTHORIZATION postgres', t_name);
          RETURN 1;
        END
      $BODY$
      LANGUAGE plpgsql VOLATILE
      COST 100;
    ALTER FUNCTION spa.create_tenant(character varying)
    OWNER TO postgres;
    

    더미 값을 반환하도록 함수를 변경 한 후에는 저장 프로 시저 쿼리를 다음과 같이 변경하십시오.

    StoredProcedureQuery query = entityManager
        .createStoredProcedureQuery("spa.create_tenant")
        .registerStoredProcedureParameter(1, 
            Long.class, ParameterMode.OUT)
        .registerStoredProcedureParameter(2, 
            String.class, ParameterMode.IN)
        .setParameter(2, name);
    
    query.getResultList();
    
  4. ==============================

    4.스프링 데이터를 사용하는 경우, @Repository 인터페이스 안에 프로 시저를 정의 할 수 있습니다.

    스프링 데이터를 사용하는 경우, @Repository 인터페이스 안에 프로 시저를 정의 할 수 있습니다.

    @Procedure(value = "spa.create_tenant")
    public void createTenantOrSomething(@Param("t_name") String tNameOrSomething);
    

    문서에 더 있습니다.

  5. ==============================

    5.간단하게 유지하려면 다음과 같이하십시오.

    간단하게 유지하려면 다음과 같이하십시오.

        em.createSQLQuery("SELECT * FROM spa.create_tenant(:t_name) ")
                              .setParameter("t_name", name)").list();
    

    Notice () 의도적으로 list ()를 사용했습니다. 어떤 이유로 .update ()가 작동하지 않았습니다.

  6. from https://stackoverflow.com/questions/26122796/how-to-properly-call-postgresql-functions-stored-procedures-within-spring-hibe by cc-by-sa and MIT license