본문 바로가기
Framework and Tool/JPA

JPA - 객체지향 쿼리 언어 - Criteria 파라미터, 네이티브 함수

by ocwokocw 2021. 8. 12.

- 참조: 자바 ORM 표준 JPA 프로그래밍

- 파라미터

JPQL 에서 :username 으로 파라미터를 정의한것처럼 Criteria 에서도 해당 기능을 제공한다.

 

CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Member> cq = cb.createQuery(Member.class);

Root<Member> m = cq.from(Member.class);

cq.select(m)
	.where(cb.equal(m.get("name"), 
		cb.parameter(String.class, "userNameParam")));

List<Member> members = em.createQuery(cq)
	.setParameter("userNameParam", "Name#4")
	.getResultList();


members.forEach(member -> {
	System.out.println("UserName: " + member.getName() + 
			", Age: " + member.getAge());
});

 

JPQL 처럼 Parameter 를 사용하기 위해 핵심적으로 살펴볼 부분은 where 절과 파라미터를 넘기는 부분이다. 앞에서 언급한 CriteriaQuery 로는 에약어들을 CriteriaBuilder 로는 비교표현식들을 설정한다는 큰틀에 따라 예약어가 아닌 parameter 는 CriteriaBuilder 에서 작성한다. 1번째 인자는 타입이며 2번째 인자는 바인딩할 파라미터 명이다.

 

파라미터 세팅 부분은 JPQL 처럼 엔티티 매니저에서 createQuery 를 사용하기 때문에 setParameter 함수를 사용한다.

 

Hibernate: 
    /* select
        generatedAlias0 
    from
        Member as generatedAlias0 
    where
        generatedAlias0.name=:userNameParam */ select
            member0_.member_id as member_i1_6_,
            member0_.insert_datetime as insert_d2_6_,
            member0_.update_datetime as update_d3_6_,
            member0_.city as city4_6_,
            member0_.street as street5_6_,
            member0_.zipcode as zipcode6_6_,
            member0_.age as age7_6_,
            member0_.name as name8_6_ 
        from
            member member0_ 
        where
            member0_.name=?
UserName: Name#4, Age: 22

 

실행해보면 역시나 잘 나오는것을 알 수 있다.


- 네이티브 함수 호출

특수한 경우에는 네이티브 SQL 함수를 호출해야할 수도 있다. Criteria 는 네이티브 함수를 호출할 수 있는 기능을 지원한다. 네이티브 함수 호출을 이용해서 회원들의 나이 합계를 구하는 SUM 함수를 구해보자.

 

CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Integer> cq = cb.createQuery(Integer.class);

Root<Member> m = cq.from(Member.class);

Expression<Integer> function = cb.function("SUM", Integer.class, m.get("age"));
cq.select(function);

List<Integer> memberAges = em.createQuery(cq)
	.getResultList();

Integer sumOfAges = memberAges.stream()
	.reduce(0, (a, b) -> a + b);
System.out.println("sumOfAges : " + sumOfAges);

 

네이티브 함수를 사용하는 표현식은 CriteriaBuilder 의 function 메소드를 이용한다. 하지만 위의 코드를 그대로 수행하면 에러가 나는데 방언에 사용자 정의 SQL 함수를 등록해줘야 한다.

 

public class ExampleH2Dialect extends H2Dialect{

	public ExampleH2Dialect() {
		super();
		
		registerFunction("SUM", 
			new StandardSQLFunction("SUM"));
	}
	
}

............

<property name="hibernate.dialect" value="com.example.demo.member.dialect.ExampleH2Dialect" />

 

H2Dialect 를 상속받아서 사용할 함수를 등록해주고 persistence.xml 에도 dialect 를 등록해준다.

 

Hibernate: 
    /* select
        function('SUM',
        generatedAlias0.age) 
    from
        Member as generatedAlias0 */ select
            SUM(member0_.age) as col_0_0_ 
        from
            member member0_
sumOfAges : 77

 

결과를 실행하면 위와 같이 SUM 함수를 이용하여 멤버의 나이의 합을 구할 수 있다.

댓글