사용 이유
- JPA를 사용하면 엔티티 객체를 중심으로 개발
- 문제는 검색 쿼리
- 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
- 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
- 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요
String jpql = "select m From Member m where m.name like ‘%hello%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
//Criteria 사용 준비
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);
//루트 클래스 (조회를 시작할 클래스)
Root<Member> m = query.from(Member.class);
//쿼리 생성
CriteriaQuery<Member> cq = query.select(m).where(cb.equal(m.get("username"), “kim”));
List<Member> resultList = em.createQuery(cq).getResultList();
//JPQL
//select m from Member m where m.age > 18
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list =
query.selectFrom(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch();
** JPQL만 잘하면 됨.. QueryDSL은 JPQL 문법알면 쉽게 할 수 있음. 메뉴얼이 잘 나와있음.
String sql =
“SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = ‘kim’";
List<Member> resultList =
em.createNativeQuery(sql, Member.class).getResultList();
select
COUNT(m), //회원수
SUM(m.age), //나이 합
AVG(m.age), //평균 나이
MAX(m.age), //최대 나이
MIN(m.age) //최소 나이
from Member m
// 반환 타입이 Member로 명확
TypedQuery<Member> query =
em.createQuery("SELECT m FROM Member m", Member.class);
Query query =
em.createQuery("SELECT m.username, m.age from Member m");
query.getResultList()
: 결과가 하나 이상일 때, 리스트 반환query.getSingleResult()
: 결과가 정확히 하나, 단일 객체 반환javax.persistence.NoResultException
javax.persistence.NonUniqueResultException
SELECT m FROM Member m where m.username=:username
query.setParameter("username", usernameParam);
SELECT m FROM Member m where m.username=?1
query.setParameter(1, usernameParam);
List<Member> result = em.createQuery("select m from Member m", Member.class)
.getResultList();
Member findMember = result.get(0);
findMember.setAge(20);
em.createQuery("select o.Address from Order o", Address.class)
.getResultList();
em.createQuery("select distinct m.username, m.age from Member m", Member.class)
.getResultList();
List resultList = em.createQuery("select m.username, m.age from Member m", Member.class);
Object o = resultList.get(0);
Object[] result = (Object[]) o;
List<Object[]> resultList = em.createQuery("select m.username, m.age from Member m", Member.class);
Object[] result = resultList.get(0);
List<Object[]> resultList = em.createQuery("select new jpabook.jpql.MemberDTO(m.username, m.age) from Member m", MemberDTO.class);
MemberDTO memberDTO = result.get(0);
//페이징 쿼리(H2)
String jpql = "select m from Member m order by m.name desc";
List<Member> resultList = em.createQuery(jpql, Member.class)
.setFirstResult(10)
.setMaxResults(20)
.getResultList();
MySQL 방언
SELECT
M.ID AS ID,
M.AGE AS AGE,
M.TEAM_ID AS TEAM_ID,
M.NAME AS NAME
FROM
MEMBER M
ORDER BY
M.NAME DESC LIMIT ?, ?
Oracle 방언
SELECT * FROM
( SELECT ROW_.*, ROWNUM ROWNUM_
FROM
( SELECT
M.ID AS ID,
M.AGE AS AGE,
M.TEAM_ID AS TEAM_ID,
M.NAME AS NAME
FROM MEMBER M
ORDER BY M.NAME
) ROW_
WHERE ROWNUM <= ?
)
WHERE ROWNUM_ > ?
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
member.setAge(10);
member.setTeam(team);
em.persist(member);
em.flush();
em.clear();
String query = "select m from Member m inner join m.team t"; // 내부 조인
String query2 = "select m from Member m left join m.team t"; // 외부 조인
String query3 = "select m from Member m, Team t where m.username = t.name"; // 세타 조인
List<Member> result = em.createQuery(query, Member.class)
.getResultList();
예) 회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인
SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'
SELECT m.*, t.* FROM Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name='A'
예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
SELECT m, t FROM Member m LEFT JOIN Team t on m.username = t.name
SELECT m.*, t.* FROM Member m LEFT JOIN Team t ON m.username = t.name
select m from Member m
where m.age > (select avg(m2.age) from Member m2)
select m from Member m
where (select count(o) from Order o where m = o.member) > 0
select m from Member m
where exists (select t from m.team t where t.name = ‘팀A')
select o from Order o
where o.orderAmount > ALL (select p.stockAmount from Product p)
select m from Member m
where m.team = ANY (select t from Team t)
String query = "select m.username, 'HELLO', TRUE From Member m";
List<Object[]> result = em.createQuery(query).getResultList();
String query = "select m.username, 'HELLO', TRUE From Member m"
+ "where m.type = jpql.MemberType.ADMIN";
List<Object[]> result1 = em.createQuery(query)
.getResultList();
String query = "select m.username, 'HELLO', TRUE From Member m"
+ "where m.type = :userType";
List<Object[]> result2 = em.createQuery(query)
.setParameter("userType", MemberType.ADMIN)
.getResultList();
Book book = new Book();
book.setName("JPA");
book.setAuthor("author");
em.persist(book);
// ITEM과 BOOK은 상속관계이므로 type(i)가 Book으로 나오게 됨.
em.createQuery("select i from Item i where type(i) = Book", Item.class)
.getResultList();
select
case when m.age <= 10 then '학생요금'
when m.age >= 60 then '경로요금'
else '일반요금'
end
from Member m
select
case t.name
when '팀A' then '인센티브110%'
when '팀B' then '인센티브120%'
else '인센티브105%'
end
from Team t
String query = "select coalesce(m.username, '이름 없는 회원') from Member m";
String query = "select nullif(m.username, '관리자') from Member m"
select function('group_concat', i.name) from Item i
select group_concat(i.name) from Item i
public class MyH2Dialect extend H2Dialect {
public MyH2Dialect() {
registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
}
}
<property name="hibernate.dialect" value="org.hibernate.dialect.MyH2Dialect"/>
관리자1,관리자2
의 결과가 출력된다.Member member1 = new Member();
member1.setName("관리자1");
em.persist(member1);
Member member2 = new Member();
member2.setName("관리자2");
em.persist(member2);
String query = "select function('group_concat', m.name) from Member m";
List<String> result = em.createQuery(query, String.class)
.getResultList();
for(String s : result) System.out.println(s); // 관리자1,관리자2