JPQL
QueryDSL
EntityManager.find()
a.getB().getC()
)String sql = "select m from Member.class as m where m.username like '%k%'";
// JPQL
// select m from Member m where m.age > 18
JPAFactoryQuery queryFactory= new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list = queryFactory.selectFrom(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch()
...
List<Member> list = query.selectFrom(m)
.wheree(m.age.gt(18)) // 컴파일 시점에서 오류 검출 가능
.orderBy(m.name.desc())
.fetch()
String sql ="SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = ‘kim’";
List<Member> resultList = em.createNativeQuery(sql, Member.class)
.getResultList();
Member member = new Member();
member.setUsername("catsbi");
conn.createQuery("select * from Member where username = 'catsbi'");
// 결과 없음
member는 Jdbc가 쿼리를 수행하는 시점에서 영속성 컨텍스트에만 있고 db에 아직 저장되지 않았기 때문에 조회 결과가 없다 그러므로 쿼리 수행 전 수동으로 플러시를 해줘야 한다.
TypedQuery<Member> query = em.createQuery("SELECT m FROM Meber m", Member.class);
Query query = em.createQuery("SELECT m.username, m.age FROM Meber m");
query.getResultList()
: 결과가 하나 이상일 때 리스트 반환query.getSingleResult()
: 결과가 정확히 하나
javax.persistence.NoResultException
javax.persistence.NonUniqueResultException
m
FROM Member m → 엔티티 프로젝션m.team
FROM Member m → 엔티티 프로젝션m.address
FROM Member m → 임베디드 타입 프로젝션m.username, m.age
FROM Member m → 스칼라 타입 프로젝션List<Team> result = em.createQuery("select m.team from Member m", Team.calss)
// SQL : SELECT t.id, t.name FROM Member m inner join TEAM t on m.team_id = t.id
List<Team> result = em.createQuery("select t from Member m join m.team t", Team.calss)
// SQL : SELECT t.id, t.name FROM Member m inner join TEAM t on m.team_id = t.id
em.createQuery("select o.address from Order o", Address.calss).getRresultList();
// SQL : SELECT o.city, o.street, o.zipcode FROM ORDERS o
임베디드 타입은 따로 조인을 해서 가져오지는 않는다. 다만, from 절에 Order가 아닌 Address를 적으면 에러가 난다. 엔티티로부터 시작돼야 한다.
em.createQuery("select distinct m.address, m.age from Member m").getRresultList();
Query 타입으로 조회
Object[] 타입으로 조회
SELECT new jpabook.jpql.UserDTO(m.username, m.age)from Memer m;
em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(0)
.setMaxResults(10)
.getReulstList();
기존에는 Diarect 별로 방언을 맞춰서 쿼리를 직접 구현해야 했는데, 이제는 두 개의 함수로 해결할 수 있다.
SELECT m FROM Member m [INNER] JOIN m.team t
SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
select count(m) from Member m, Team t where m.username = t.name
ex) 회원과 팀을 조인하면서, 팀 이름이 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'
ex) 회원의 이름과 팀의 이름이 같은 대상 외부 조인
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.username
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)
JPA는 WHERE, HAVING 절에서만 서브 쿼리 사용 가능
SELECT 절도 가능 (하이버네이트에서 지원)
jpabook.MemberType.Admin (패키지명 포함)
select m.username, 'HELLO', true from Member m
where m.type = jpql.MemberType.ADMIN
TYPE(m)= Member (상속 관계에서 사용)
em.createQuery("select i from Item i where type(i) = Book", Item.class);
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
COALESCE
: 하나씩 조회해서 null이 아니면 반환select coalesce(m.username, '이름 없는 회원') from Member m;
NULLIF
: 두 값이 같으면 null 반환, 다르면 첫번째 값 반환select NULLIF(m.username, '관리자') from Member ;
// CONCAT
select concat('a','b'); // ab
// SUBSTRING : firstParam의 값을 secondParam 위치부터 thirdParam 개수만큼 잘라서 반환
select substring('abcd', 2,3) // bc
// TRIM
select trim(' lee han sol ') // lee han sol
// LOWER, UPPER
select LOWER('hansolHI'); // hansolhi
select UPPER('hansolHI'); // HANSOLHI
// LENGTH
select LENGTH('hansolHI'); // 6
// LOCATE
select LOCATE('so', 'hansol'); // 4
// ABS, SQRT, MOD
select ABS(-30); // 30
select SQRT(4); // 2
select MOD(4,2); // 0
// SIZE, INDEX (JPA 용도)
select SIZE(t.members) from Team t // 0
// group_concat이라는 함수를 만들어서 등록한다고 가정한다.
public class MyPostgresDialect extends PostgreSQL94Dialect {
public MyPostgresDialect() {
registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
}
...
...
...
// 설정 파일 등록
<property name="hibernate.dialect" value="jpql.MyPostgresDialect"/>