NativeSQL
jpql์ ํ์ค SQL์ด ์ง์ํ๋ ๋๋ถ๋ถ์ ๋ฌธ๋ฒ๊ณผ SQLํจ์๋ค์ ์ง์ํ์ง๋ง, ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ข ์์ ์ธ ๊ธฐ๋ฅ์ ์ง์ํ์ง ์์ ์๋ฅผ ๋ค๋ฉด ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง ์ง์ํ๋ ํจ์, ๋ฌธ๋ฒ, SQL์ฟผ๋ฆฌ ํํธ ์ธ๋ผ์ธ ๋ทฐ, union, intersect ์คํ ์ด๋ ํ๋ก์์ ๋ฑ๋ฑ์ด ์๋ค ๋ค์ดํฐ๋ธ SQL์ ์ฌ์ฉํ๋ ์ด์ ๋ JPQL์ ์ฌ์ฉํ ์ ์๋ ๊ฒฝ์ฐ์์ ์ง์ SQL์ ์ฌ์ฉํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ค JPQL์ ์ฌ์ฉํ๋ฉด JPA๊ฐ SQL์ ์์ฑํ๋๋ฐ, ๋ค์ดํฐ๋ธSQL์ ๊ฐ๋ฐ์๊ฐ ์ง์ ์ ์ํ๋ค๋ ์ ๊ทธ๋ผ jdbc์ api๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ jpa๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ด๋ค ์ฐจ์ด๊ฐ ์๋? -> ๋ค์ดํฐ๋ธSQL์ ์ฌ์ฉํ๋ค๋ฉด ์ํฐํฐ๋ฅผ ์กฐํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๊ณ JPA๊ฐ ์ง์ํ๋ ์์์ฑ ์ปจํ ์คํธ์ ๊ธฐ๋ฅ์ ๊ทธ๋๋ก ์ฌ์ฉ -> JDBC API๋ฅผ ์ง์ ์ฌ์ฉํ๋ฉด ๋จ์ํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋์ด
##๋ค์ดํฐ๋ธ SQL์ ์ฌ์ฉ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ api์๋ 3๊ฐ์ง๊ฐ ์กด์ฌ
//๊ฒฐ๊ณผ ํ์
์ ์ ์
public Query createNativeQuery(String sqlString, Class resultClass);
//๊ฒฐ๊ณผ ํ์
์ ์ ์ํ ์ ์์ ๋
public Query createNativeQuery(String sqlString);
public Query createNativeQuery(String sqlString, String resultSetMapping);
์ํฐํฐ ์กฐํ
๋ญ ๊ทธ๋ ๊ฒ ๋ค๋ฅธ์ ์ ์๋ค..! ๋ค์ดํฐ๋ธ SQL๋ก SQL๋ง ์ง์ ์ฌ์ฉํ ๋ฟ์ด์ง ๋๋จธ์ง๋ JPQL์ ์ฌ์ฉํ ๋์ ๊ฐ์ผ๋ฉฐ ์กฐํํ ์ํฐํฐ๋ ์์์ฑ ์ปจํ ์คํธ๋ก ๊ด๋ฆฌ๋๋ค
String sql = "SELECT ID, AGE, NAME, TEAM_ID FROM MEMBER WHERE AGE > ?";
Query nativeQuery = em.createNativeQuery(sql, Member.class).setParameter(1, 20);
List<Member> resultList = nativeQuery.getResultList();
๊ฐ ์กฐํ
๋จ์ํ๊ฒ ๊ฐ์ผ๋ก๋ง๋ ์กฐํํ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค
String sql = "SELECT ID, AGE, NAME, TEAM_ID FROM MEMBER WHERE AGE > ?";
Query nativeQuery = em.createNativeQuery(sql).setParameter(1, 10);
List<Object[]> resultList = nativeQuery.getResultList();
for(Object[] row : resultList){
System.out.println("id = " + row[0]);
System.out.println("age = " + row[1]);
System.out.println("name = " + row[2]);
System.out.println("team_id = " + row[3]);
}
์ํฐํฐ๋ก ์กฐํํ๋ ๊ฒ์ด ์๋๋ผ ๋จ์ํ๊ฒ ๊ฐ์ผ๋ก ์กฐํํ๊ธฐ ์ํด์ class๋ฅผ ๋ ๋ฒ์จฐ ํ๋ผ๋ฏธํฐ์ ์ค์ ํด์ฃผ์ง ์์ ๋ชจ์ต์ด๊ณ ์กฐํ๋ ๊ฐ์ ์ํฐํฐ๊ฐ ์๋ ๊ฐ์๋ค๊ฐ ๋ฃ์ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ Object[]์ ๋ด์์ ๋ฐํํ๋ค ์ฌ๊ธฐ์๋ ์ค์นผ๋ผ ๊ฐ๋ค์ ์กฐํํ์ ๋ฟ์ด๊ธฐ ๋๋ฌธ์ ๊ฒฐ๊ณผ๋ฅผ ์์์ฑ ์ปจํ ์คํธ๊ฐ ๊ด๋ฆฌํ์ง ์๋๋ค๋ ์ !!
๊ฒฐ๊ณผ ๋งคํ ์ฌ์ฉ
๋ง์ฝ์ ์ํฐํฐ์ ์ค์นผ๋ผ ๊ฐ์ ํจ๊ป ์กฐํํ๋ ๊ฒ ์ฒ๋ผ ๋งคํ์ด ๋ณต์กํด์ง๋ฉด @SqlResultSetMapping์ ์ ์ํด์ ๊ฒฐ๊ณผ ๋งคํ์ ์ฌ์ฉํด์ผ ํจ ์ฌ์ฉํ๋ ์์๋ฅผ ๋ณด์
String sql = "SELECT M.ID, AGE, NAME, TEAM_ID, I.ORDER_COUNT FROM MEMBER M" +
"LEFT JOIN " +
"(SELECT IM.ID, COUNT(*) AS ORDER_COUNT " +
"FROM ORDERS O, MEMBER IM " +
"WHERE O.MEMBER_ID = IM.ID) I " +
"ON M.ID = I.ID";
Query nativeQuery = em.createNativeQuery(sql, "memberWithOrderCount");
List<Object[]> resultList = nativeQuery.getResultList();
for(object[] row : resultList){
Member member = (Member) row[0];
BigInteger orderCount = (BigInteger)row[1];
System.out.println("member = " + member);
System.out.println("orderCount = " + orderCount);
}
์ด๋ ๊ฒ ๋ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ์ ๊ฒฐ๊ณผ ๋งคํ ์ ๋ณด์ ์ด๋ฆ์ด ์ฌ์ฉ๋์์ ์ด๋ ๊ฒ ๊ฒฐ๊ณผ ๋งคํ์ ํด๋ณผ ์ ์๋ค๋ ์ ์ด๋ค
@Entity
@SqlResultSetMapping(name = "memberWithOrderCount",
entities = {@EntityResult(entityClass = Member.class),
columns = {@ColumnResult(name = "ORDER_COUNT")}
public class Member{ ...}
memberWithOrderCount์ ๊ฒฐ๊ณผ ๋งคํ์ Member ์ํฐํฐ์ ORDER_COUNT ์นผ๋ผ์ ๋งคํํ๋๋ฐ, ๋งคํํ๋ ๊ฒ์ ๋ค์์ ์ํฐํฐ์ ๋ค์์ ์ปฌ๋ผ์ ์ด์ด์ฃผ๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค @EntityResult ์ด์ธ์๋ @FieldResult ๋ผ๋ ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ ์ปฌ๋ผ๋ช ๊ณผ ํ๋๋ช ์ ์ง์ ๋งคํํ๋ ๊ฒ๋ ๊ฐ๋ฅ
๊ฒฐ๊ณผ ๋งคํ ์ ๋
ธํ
์ด์
@SqlResultSetMapping
name : ๊ฒฐ๊ณผ ๋งคํ ์ด๋ฆ
entities : @EntityResult๋ฅผ ์ฌ์ฉํด์ ์ํฐํฐ๋ฅผ ๊ฒฐ๊ณผ๋ก ๋งคํ
columns : @ColumnResult๋ฅผ ์ฌ์ฉํด์ ์ปฌ๋ผ์ ๊ฒฐ๊ณผ๋ก ๋งคํ
@EntityResult
entityClass : ๊ฒฐ๊ณผ๋ก ์ฌ์ฉํ ์ํฐํฐ ํด๋์ค๋ฅผ ์ง์
fields : @FieldResult์ ์ฌ์ฉํด์ ๊ฒฐ๊ณผ ์ปฌ๋ผ์ ํ๋์ ๋งคํ
discriminatorColumn : ์ํฐํฐ์ ์ธ์คํด์ค ํ์ ์ ๊ตฌ๋ถํ๋ ํ๋(์์ํ ๋ ์ฌ์ฉ)
@FieldResult
name : ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ ํ๋๋ช
column : ๊ฒฐ๊ณผ ์ปฌ๋ผ๋ช
@ColumnResult
name : ๊ฒฐ๊ณผ ์ปฌ๋ผ๋ช
Named ๋ค์ดํฐ๋ธ SQL
JPQL์์ ์ฒ๋ผ ๋ค์ดํฐ๋ธSQL๋ Named ๋ค์ดํฐ๋ธ SQL์ ์ฌ์ฉํด์ ์ ์ SQL์ ์์ฑํ ์ ์๋ค
@Entity
@NamedNativeQuery(
name = "Member.memberSQL",
query = "SELECT ID, AGE, NAME, TEAM_ID FROM MEMBER WHERE AGE > ?", resultClass = Member.class
)
public class Member { ... }
@NamedNativeQuery ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ Named๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ๋ฑ๋กํ๊ณ ์ฌ์ฉ์ ์ด๋ ๊ฒ
TypedQuery<Member> nativeQuery = em.createQuery("Member.memberSQL", Member.class).setParameter(1, 20);
์ฌ์ฉ๋ฟ๋ง ์๋๋ผ ๊ฒฐ๊ณผ ๋งคํ ์์ฒด๋
@Entity
@SqlResultSetMapping(name = "memberWithOrderCount",
entities = {@EntityResult(entityClass = Member.class)},
columns = {@ColumnResult(name = "ORDER_COUNT")}
)
@NamedNativeQuery(
name = "Member.memberWithOrderCount",
query = "SELECT M.ID, NAME, TEAM_ID, I.ORDER_COUNT FROM MEMBER M" +
"LEFT JOIN (SELECT IM.ID, COUNT(*) AS ORDER_COUNT " +
"FROM ORDERS O, MEMBER IM " +
"WHERE O.MEMBER_ID = IM.ID) I " +
"ON M.ID = I.ID",
resultSetMapping = "memberWithOrderCount"
)
public class Member {...}
Named ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ์์ ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๋งคํ๊น์ง memberWithOrderCount์ ๋ง์ถฐ์คฌ๊ณ
List<Object[]> resultList = em.createNamedQuery("Member.memberWithOrderCount").getResultList();
์ด๋ ๊ฒ ์ฌ์ฉํ๋ค
@NamedNativeQuery
name : ๋ค์๋ ์ฟผ๋ฆฌ ์ด๋ฆ(required)
query : SQL ์ฟผ๋ฆฌ(required)
hints : ๋ฒค๋ ์ข ์์ ์ธ ํํธ
resultClass : ๊ฒฐ๊ณผ ํด๋์ค
resultSetMapping : ๊ฒฐ๊ณผ ๋งคํ ์ฌ์ฉ
๋ค์ดํฐ๋ธ SQL ์ ๋ฆฌ
๋ค์ดํฐ๋ธ SQL์ JPQL์ด ์๋์ผ๋ก ์์ฑํ๋ SQL์ ์๋์ผ๋ก ์ง์ ์ ์ํ๋ ๊ฒ์ด ์๋๊ธฐ ๋๋ฌธ์ JPA๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ ๋๋ถ๋ถ ๊ทธ๋๋ก ์ฌ์ฉ ๊ฐ๋ฅ ๊ทผ๋ฐ ์ด๋ ๊ฒ ๋ ๊ฒ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ฐ์ ์ด์์ฑ๋ ๋จ์ด์ง๊ณ ์ข ์์ ์ด๋ผ๋ ์ ..!
์คํ ์ด๋ ํ๋ก์์ (Stored Procedure)
๊ฐ๋ ์ผ๋ก๋ ์ผ๋ จ์ ์ฟผ๋ฆฌ๋ฅผ ๋ง์น ํ๋์ ํจ์์ฒ๋ผ ์คํ ํ๊ธฐ ์ํ ์ฟผ๋ฆฌ์ ์งํฉ์ด๋ค
์์๋ก๋ ์ ๋ ฅ๊ฐ์ 2๋ฐฐ๋ก ๋ง๋ค์ด์ฃผ๋ proc_multiply๊ฐ ์๋๋ฐ jpa๋ฅผ ํธ์ถํ๋๊ฑด
StoredProcedureQuery spq = em.createStoredProcedureQuery("proc_multiply");
spq.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
spq.registerStoredProcedureParameter(2, Integer.class, ParameterMode.OUT);
spq.setParameter(1, 100);
spq.exeute();
Integer out = (Integer)spq.getOutputParameterValue(2);
System.out.println("out = " + out);
์ด๋ ๊ฒ ์ฌ์ฉํ๋ฉด out์ 200
๋ญ ๋์ถฉ ์ด๋ฐ ๊ฐ๋ ์ ์ด๋ ๊ฒ ์ฌ์ฉํ๋ค๊ณ ๋ง ์์๋๊ณ ๋์์ข ๋ณด์ด๋ฉด ๋ค์ ๊ณต๋ถํ์
Last updated
Was this helpful?