반응형
이번 포스팅에서는 nativeQuery로 프로시저를 사용하는 것이 아닌,
직접 프로시저 실행하는 명령어를 이용하여 프로시저를 사용합니다.
예제 파일은 깃허브에서 다운로드 가능합니다.
https://github.com/luvris2/spring-boot-jap-stored-procedure-query
사용 환경
- IDE : IntelliJ
- Java : Open JDK 17
- Project : Grade
- DB : SSMS (MS-SQL)
- DB Management : JPA
프로젝트 설정
설정에 대한 자세한 설명이 필요하다면 아래의 포스팅에서 통해 설정을 진행해주시면 됩니다.
https://luvris2.tistory.com/500
build.gradle - dependencies
dependencies {
// MS-SQL
runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc:9.2.1.jre11'
// JPA
implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
}
application.yml
# application.yml
spring:
datasource:
url: jdbc:sqlserver:// your host name : port ;databaseName= your DB name
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
username: your name
password: your password
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:sqlserver:// 'your host name' : 'port number';databaseName= 'your database name' "/>
<property name="javax.persistence.jdbc.user" value=" your user name "/>
<property name="javax.persistence.jdbc.password" value=" your password "/>
</properties>
</persistence-unit>
</persistence>
JPA 클래스 설정
EntityManagerFactory를 정의할 클래스
- 이름은 JpaUtils로 정의, 개인에 맞게 정의
// JpaUtils.java
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
public class JpaUtils {
private static final String PERSISTENCE_UNIT_NAME = "myPersistenceUnit"; // replace with your persistence unit name
private static final EntityManagerFactory emFactory;
static {
emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
public static EntityManager getEntityManager() {
return emFactory.createEntityManager();
}
}
Entity 클래스 정의
- 조회한 테이블의 데이터타입과 값을 반환 받기 위해 편의상 설정
- 테이블 애너테이션에 테이블 이름 입력
- 엔티티 클래스는 없어도 무관
- 단, 없을 경우 프로시저 처리 결과의 반환 값이 오브젝트 타입이며 형변환 진행해야 함
- 이름은 ProcedureResultSet 으로 정의, 개인에 맞게 정의
// ProcedureResultSet.java
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name="testTable")
public class ProcedureResultSet {
@Id
private int id;
@Column
private String username;
@Column
private String address;
}
- 테이블 확인
select * from testTable;
JPA 저장 프로시저 쿼리 문법
- createStoredProcedureQuery(프로시저명, 엔티티)
- 입력한 프로시저 실행
- 엔티티 클래스를 입력할 경우 해당 컬럼에 설정된 데이터타입으로 값 반환
- 프로시저명만 입력할 경우 오브젝트 타입으로 값 반환 (형변환 필요)
- registerStoredProcedureParameter(순서, 데이터타입, 입출력여부)
- 순서 혹은 파라미터명 : 정수의 숫자로 입력, 혹은 파라미터명을 정의하여 사용
- 데이터타입 : 데이터 타입 뒤에 .class를 붙임 (예:String.class)
- 입출력여부 : ParameterMode.IN 혹은 ParameterMode.OUT
- setParameter(순서, 값)
- 입력 파라미터에만 해당
- 순서 혹은 파라미터명 : 정수의 숫자로 입력, 혹은 파라미터명을 정의하여 사용
- 값 : 설정한 데이터타입에 맞는 형태의 값 입력
- getOutputParameterValue(순서)
- 출력 파라미터에만 해당
- 순서 혹은 파라미터명 : 정수의 숫자 혹은 파라미터명을 입력하여 해당 출력 파라미터의 값 반환
JPA 저장 프로시저 쿼리 클래스 설정
프로시저 내용
- p_select_all : 해당 테이블의 모든 내용 조회
CREATE PROC p_select_all
AS
BEGIN
select * from testTable
END
- p_select_id : 해당 테이블의 특정 아이디의 정보 조회
- 입력 파라미터 존재
CREATE PROC p_select_id
@a int
AS
BEGIN
select * from testTable where id = @a
END
- p_select_address : 해당 테이블의 특정 지역에 대한 멤버 이름 조회
- 입력 파라미터, 출력 파라미터 존재
CREATE PROC p_select_address
@address NVARCHAR(MAX),
@outValue NVARCHAR(MAX) OUT
AS
BEGIN
select @outValue = username from testTable where address = @address
END
파라미터가 없는 프로시저의 모든 값 출력
프로시저명 : p_select_all
EntityManager em = JpaUtils.getEntityManager();
/* 입출력 파라미터가 없는 프로시저 */
System.out.println("************************************************************");
System.out.println("입출력 파라미터가 없는 프로시저 호출하기");
System.out.println("테이블의 모든 데이터에 대한 조회 결과 확인");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("p_select_all", ProcedureResultSet.class);
// 쿼리의 결과를 리스트의 형태로 반환
List<ProcedureResultSet> resultList = storedProcedure.getResultList();
// 쿼리 결과를 저장할 변수 선언
ArrayList<ProcedureResultSet> resultAll = new ArrayList<>();
int i=0; // Object Index
for ( ProcedureResultSet row : resultList ) {
// 저장
resultAll.add(row);
// 값 확인
System.out.println(" 프로시저 처리 결과 : " + (i+1) + " row = "
+ resultAll.get(i).getUsername() + ", "
+ resultAll.get(i).getAddress());
i++;
}
em.close();
입력 파라미터가 있는 프로시저 값 출력
EntityManager em = JpaUtils.getEntityManager();
/* 입력 파라미터가 있는 프로시저 */
System.out.println("************************************************************");
System.out.println("입력 파라미터가 있는 프로시저 호출하기");
System.out.println("입력 파라미터는 특정 ID를 입력하여 해당 ID의 정보 확인");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedureOnlyInput = em.createStoredProcedureQuery("p_select_id", ProcedureResultSet.class);
// 저장 프로시저의 입력 파라미터 설정
storedProcedureOnlyInput.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
// 저장 프로시저의 입력 파라미터 입력(순서, 값)
storedProcedureOnlyInput.setParameter(1, 2);
// 쿼리의 결과를 리스트의 형태로 반환
List<ProcedureResultSet> result = storedProcedureOnlyInput.getResultList();
int j=0; // Object Index
for ( ProcedureResultSet row : result ) {
// 값 확인
System.out.println(" 프로시저 처리 결과 : 입력한 ID(2), 조회 결과 : "
+ result.get(j).getUsername() + ", "
+ result.get(j).getAddress());
j++;
}
em.close();
입출력 파라미터가 모두 있는 프로시저 값 출력
EntityManager em = JpaUtils.getEntityManager();
/* 출력 파라미터가 있는 프로시저 */
System.out.println("************************************************************");
System.out.println("출력 파라미터가 있는 프로시저 호출하기");
System.out.println("출력 파라미터는 특정 지역에 거주하는 사용자의 이름을 반환");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedureOutput = em.createStoredProcedureQuery("p_select_address");
// 저장 프로시저의 입력, 출력 파라미터 설정
storedProcedureOutput.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
storedProcedureOutput.registerStoredProcedureParameter(2, String.class, ParameterMode.OUT);
// 저장 프로시저의 입력 파라미터 입력(순서, 값)
storedProcedureOutput.setParameter(1, "incheon");
// 출력 파라미터의 값 저장
String outputParam = (String) storedProcedureOutput.getOutputParameterValue(2);
// 출력 파라미터의 값 확인
System.out.println(" 프로시저 처리 결과 : 입력한 지역 = incheon, 출력 파라미터의 값 = " + outputParam);
System.out.println("************************************************************");
em.close();
실행 결과
프로젝트 디렉토리 구조 및 전체 소스 코드
프로젝트 디렉토리 구조
소스 코드
config.JpaUtils
package org.example.config;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
public class JpaUtils {
private static final String PERSISTENCE_UNIT_NAME = "myPersistenceUnit"; // replace with your persistence unit name
private static final EntityManagerFactory emFactory;
static {
emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
public static EntityManager getEntityManager() {
return emFactory.createEntityManager();
}
}
config.JpaQuery
package org.example.config;
import jakarta.persistence.EntityManager;
import jakarta.persistence.ParameterMode;
import jakarta.persistence.StoredProcedureQuery;
import org.example.entity.ProcedureResultSet;
import java.util.ArrayList;
import java.util.List;
public class JpaQuery {
private static List<ProcedureResultSet> executeNamedQuery() {
EntityManager em = JpaUtils.getEntityManager();
/* 입출력 파라미터가 없는 프로시저 */
System.out.println("************************************************************");
System.out.println("입출력 파라미터가 없는 프로시저 호출하기");
System.out.println("테이블의 모든 데이터에 대한 조회 결과 확인");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("p_select_all", ProcedureResultSet.class);
// 쿼리의 결과를 리스트의 형태로 반환
List<ProcedureResultSet> resultList = storedProcedure.getResultList();
// 쿼리 결과를 저장할 변수 선언
ArrayList<ProcedureResultSet> resultAll = new ArrayList<>();
int i=0; // Object Index
for ( ProcedureResultSet row : resultList ) {
// 저장
resultAll.add(row);
// 값 확인
System.out.println(" 프로시저 처리 결과 : " + (i+1) + " row = "
+ resultAll.get(i).getUsername() + ", "
+ resultAll.get(i).getAddress());
i++;
}
/* 입력 파라미터가 있는 프로시저 */
System.out.println("************************************************************");
System.out.println("입력 파라미터가 있는 프로시저 호출하기");
System.out.println("입력 파라미터는 특정 ID를 입력하여 해당 ID의 정보 확인");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedureOnlyInput = em.createStoredProcedureQuery("p_select_id", ProcedureResultSet.class);
// 저장 프로시저의 입력 파라미터 설정
storedProcedureOnlyInput.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
// 저장 프로시저의 입력 파라미터 입력(순서, 값)
storedProcedureOnlyInput.setParameter(1, 2);
// 쿼리의 결과를 리스트의 형태로 반환
List<ProcedureResultSet> result = storedProcedureOnlyInput.getResultList();
int j=0; // Object Index
for ( ProcedureResultSet row : result ) {
// 값 확인
System.out.println(" 프로시저 처리 결과 : 입력한 ID(2), 조회 결과 : "
+ result.get(j).getUsername() + ", "
+ result.get(j).getAddress());
j++;
}
/* 출력 파라미터가 있는 프로시저 */
System.out.println("************************************************************");
System.out.println("출력 파라미터가 있는 프로시저 호출하기");
System.out.println("출력 파라미터는 특정 지역에 거주하는 사용자의 이름을 반환");
// 저장 프로시저 쿼리, 저장 프로시저의 이름 입력
StoredProcedureQuery storedProcedureOutput = em.createStoredProcedureQuery("p_select_address");
// 저장 프로시저의 입력, 출력 파라미터 설정
storedProcedureOutput.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
storedProcedureOutput.registerStoredProcedureParameter(2, String.class, ParameterMode.OUT);
// 저장 프로시저의 입력 파라미터 입력(순서, 값)
storedProcedureOutput.setParameter(1, "incheon");
// 출력 파라미터의 값 저장
String outputParam = (String) storedProcedureOutput.getOutputParameterValue(2);
// 출력 파라미터의 값 확인
System.out.println(" 프로시저 처리 결과 : 입력한 지역 = incheon, 출력 파라미터의 값 = " + outputParam);
System.out.println("************************************************************");
em.close();
return null;
}
public static List<ProcedureResultSet> doNameQuery() {
return executeNamedQuery();
}
}
entity.ProcedureResultSet
package org.example.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
@Table(name="testTable")
public class ProcedureResultSet {
@Id
private int id;
@Column
private String username;
@Column
private String address;
}
Main
package org.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import static org.example.config.JpaQuery.doNameQuery;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
// 쿼리 실행
doNameQuery();
}
}
반응형