스프링

 

✍️
이런 걸
배워요!

JPA의 기본기를 탄탄하게 다질 수 있습니다.

JPA의 내부 동작 방식을 이해할 수 있습니다.

객체와 DB 테이블을 올바르게 설계하고 매핑할 수 있습니다.

실무에서 자신있게 JPA를 사용할 수 있습니다.

 

 

인프런 강의 :  https://www.inflearn.com/course/ORM-JPA-Basic

 

강의 자료 : 

https://github.com/braverokmc79/jpa-basic-lecture-file

 

 

소스 :

https://github.com/braverokmc79/ex-jpa-13-1

 

https://github.com/braverokmc79/jpa-shop

 

https://github.com/braverokmc79/ORM-JPA-Basic-jpql

 

 

 

 

 

[9] 객체지향 쿼리 언어1 - 기본 문법

 

 

35.  소개

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21718&tab=curriculum

 

 

목차
• 객체지향 쿼리 언어 소개
• JPQL
• 기본 문법과 기능
• 페치 조인
• 경로 표현식
• 다형성 쿼리
• 엔티티 직접 사용
• Named 쿼리
• 벌크 연산

 

 

 

JPA는 다양한 쿼리 방법을 지원
• JPQL
• JPA Criteria
• QueryDSL
• 네이티브 SQL
• JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용

 

 

 

JPQL
• JPA를 사용하면 엔티티 객체를 중심으로 개발
• 문제는 검색 쿼리
• 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
• 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
• 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검
색 조건이 포함된 SQL이 필요

 

 

 

 

JPQL
• JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
• SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
• JPQL은 엔티티 객체를 대상으로 쿼리
• SQL은 데이터베이스 테이블을 대상으로 쿼리

 

 

 

JPQL

//검색
 String jpql = "select m From Member m where m.name like ‘%hello%'";
 List<Member> result = em.createQuery(jpql, Member.class)
 .getResultList();

 

 

 

JPQL
• 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
• SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
• JPQL을 한마디로 정의하면 객체 지향 SQL

 

 

 

 

JPQL과 실행된 SQL

 //검색
 String jpql = "select m from Member m where m.age > 18";
 List<Member> result = em.createQuery(jpql, Member.class)
 .getResultList(

 

실행된 SQL
 select
 m.id as id,
 m.age as age,
 m.USERNAME as USERNAME,
 m.TEAM_ID as TEAM_ID
 from
 Member m
 where
 m.age>18

 

 

 

 

Criteria 소개

//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();

 

 

 

 

Criteria 소개

 문자가 아닌 자바코드로 JPQL을 작성할 수 있음
• JPQL 빌더 역할
• JPA 공식 기능
• 단점: 너무 복잡하고 실용성이 없다.
• Criteria 대신에 QueryDSL 사용 권장

 

 

 

 

QueryDSL 소개

 //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();

 

 

 

QueryDSL 소개
• 문자가 아닌 자바코드로 JPQL을 작성할 수 있음
• JPQL 빌더 역할
• 컴파일 시점에 문법 오류를 찾을 수 있음
• 동적쿼리 작성 편리함
• 단순하고 쉬움
• 실무 사용 권장

 

 

 

 

네이티브 SQL 소개
• JPA가 제공하는 SQL을 직접 사용하는 기능
• JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능
• 예) 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트

 

 

 

네이티브 SQL 소개

String sql =
 “SELECT ID, AGE, TEAM_ID, NAME FROM MEMBER WHERE NAME = ‘kim’";
List<Member> resultList =
 em.createNativeQuery(sql, Member.class).getResultList(); 

 

 

 

 

JDBC 직접 사용, SpringJdbcTemplate 등


• JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스프링 JdbcTemplate, 마이바티스등을 함께 사용 가능
• 단 영속성 컨텍스트를 적절한 시점에 강제로 플러시 필요
• 예) JPA를 우회해서 SQL을 실행하기 직전에 영속성 컨텍스트 수동 플러시

 

 

 

 

 

 

36.  기본 문법과 쿼리 API

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21719&tab=curriculum

 

 

JPQL 소개

• JPQL은 객체지향 쿼리 언어다.따라서 테이블을 대상으로 쿼리 하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
• JPQL은 SQL을 추상화해서 특정데이터베이스 SQL에 의존하 지 않는다.
• JPQL은 결국 SQL로 변환된다. 

 

 

 

 

Member

@Entity
@Getter
@Setter
public class Member {

	@Id
	@GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;

	@Column(name = "USERNAME")
	private String username;

	private int age;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "TEAM_ID")
	private Team team;

}

 

Address

@Embeddable
@Getter
public class Address {
	
	private String city;
	private String street;
	private String zipcode;
	
	public Address() {
		
	}
	
	public Address(String city, String street, String zipcode) {
		this.city = city;
		this.street = street;
		this.zipcode = zipcode;
	}

	@Override
	public int hashCode() {
		return Objects.hash(city, street, zipcode);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Address other = (Address) obj;
		return Objects.equals(city, other.city) && Objects.equals(street, other.street)
				&& Objects.equals(zipcode, other.zipcode);
	}

}

 

 

Order

/**
 * Order 주의 Order 는 예약어라 Orders 사용
 */
@Entity
@Getter
@Table(name="ORDERS")
public class Order {
	
	@Id
	@GeneratedValue
	@Column(name="ORDER_ID")
	private Long id;
	
	private int orderAmount;
	
	@Embedded
	private Address address;
	
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name="PRODUCT_ID")
	private Product product;
	

}

 

Product

@Entity
@Getter
public class Product {

	@Id @GeneratedValue
	@Column(name="PRODUCT_ID")
	private Long id;
	
	private String name;
	
	private int price;
	
	private int stockAmount;
}

 

 

Team

@Entity
@Getter
public class Team {

	@Id
	@GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;

	private String name;

	@OneToMany(mappedBy = "team")
	private List<Member> members = new ArrayList<Member>();

}

 

 

 

 

 

 

 

 

 

JPQL 문법

 

select_문 :: =
 select_절
 from_절
 [where_절]
 [groupby_절]
 [having_절]
 [orderby_절]
update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]

 

 

 

 

JPQL 문법
 

select m from Member as m where m.age > 18

• 엔티티와 속성은 대소문자 구분O (Member, age)
• JPQL 키워드는 대소문자 구분X (SELECT, FROM, where)
• 엔티티 이름 사용, 테이블 이름이 아님(Member)
별칭은 필수(m) (as는 생략가능)

 

 

 

 

집합과 정렬

 

select
 COUNT(m), //회원수
 SUM(m.age), //나이 합
 AVG(m.age), //평균 나이
 MAX(m.age), //최대 나이
 MIN(m.age) //최소 나이
from Member m

 

 

 

집합과 정렬
• GROUP BY, HAVING
• ORDER BY

 

 

TypeQuery, Query

TypeQuery: 반환 타입이 명확할 때 사용
• Query: 반환 타입이 명확하지 않을 때 사용

 

TypedQuery<Member> query =
 em.createQuery("SELECT m FROM Member m", Member.class); 

 

Query query =
 em.createQuery("SELECT m.username, m.age from Member m");

 

 

 

 

 

결과 조회 API

 

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);

 

 

 

 

 

 

 

 

 

 

37.  프로젝션(SELECT)

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21720&tab=curriculum

 

프로젝션(SELECT)


• SELECT 절에 조회할 대상을 지정하는 것

 

• 프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자등 기본 데이터 타 입)


SELECT m FROM Member m -> 엔티티 프로젝션


SELECT m.team FROM Member m -> 엔티티 프로젝션


SELECT m.address FROM Member m -> 임베디드 타입 프로젝션


SELECT m.username, m.age FROM Member m -> 스칼라 타입 프로젝션


DISTINCT로 중복 제거

 

JpaMain

package jpashop.jpql;


import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import jpashop.home.domain.Member;
import jpashop.home.domain.MemberDTO;
import jpashop.home.domain.Team;

public class JpaMain {
	public static void main(String[] args) {
		EntityManagerFactory emf=Persistence.createEntityManagerFactory("hello");
		
		EntityManager em=emf.createEntityManager();
		
		//JPA 의 모든 데이터 변경은  트랜잭션 안에서 실행 되어야 한다.
		EntityTransaction tx=em.getTransaction();
		tx.begin();
			
		try {
			
			Member member=new Member();
			member.setUsername("member1");
			member.setAge(10);
			em.persist(member);
			
			em.flush();
			em.clear();
			
//			List<Member> result =em.createQuery("select m from Member m", Member.class).getResultList();
//			
//			
//			Member findMember =result.get(0);
//			findMember.setAge(30);
			
			/** 조인을 할경우 다음과 같이 명시적으로 조인을 해라 **/
			//List<Team> result =em.createQuery("select t from Member m join m.team t", Team.class).getResultList();
			
			
			/** 타입이 여러 가지 일경우  */
			/** 방법 1  */
			List resultList =em.createQuery("select m.username, m.age from Member m ").getResultList();
			Object o =resultList.get(0);
			Object[] result =(Object[]) o;
			System.out.println("방법 1 username = " +result[0]);
			System.out.println("방법 1 age = " +result[1]);
			
			
			/** 방법 2  */
			List<Object[]> resultList2 =em.createQuery("select m.username, m.age from Member m ").getResultList();
			Object[] reuslt2=resultList2.get(0);
			System.out.println("방법 2 username = " +reuslt2[0]);
			System.out.println("방법 2 age = " +reuslt2[1]);
			
			
			
			/** 방법 3  항상 new 와 jpql  적고 생성자를 호툴하듯이 하면 된다.*/
			List<MemberDTO> resultList3 =em.createQuery("select new jpashop.home.domain.MemberDTO(m.username, m.age) from Member m ", MemberDTO.class).getResultList();
			MemberDTO memberDTO=resultList3.get(0);
			System.out.println("방법 2 username = " +memberDTO.getUsername());
			System.out.println("방법 2 age = " +memberDTO.getAge());
			
			
			
			tx.commit();
		}catch(Exception e) {
			tx.rollback();
			e.printStackTrace();
		}finally {
			em.close();
		}
	
		
		emf.close();	
	}
	

}

 

 

 

프로젝션 - 여러 값 조회
 

• SELECT m.username, m.age FROM Member m

 


1. Query 타입으로 조회

			/** 타입이 여러 가지 일경우  */
			/** 방법 1  */
			List resultList =em.createQuery("select m.username, m.age from Member m ").getResultList();
			Object o =resultList.get(0);
			Object[] result =(Object[]) o;
			System.out.println("방법 1 username = " +result[0]);
			System.out.println("방법 1 age = " +result[1]);

 

 


 2. Object[] 타입으로 조회

			/** 방법 2  */
			List<Object[]> resultList2 =em.createQuery("select m.username, m.age from Member m ").getResultList();
			Object[] reuslt2=resultList2.get(0);
			System.out.println("방법 2 username = " +reuslt2[0]);
			System.out.println("방법 2 age = " +reuslt2[1]);
			

 

 


3. new 명령어로 조회

			/** 방법 3  항상 new 와 jpql  적고 생성자를 호툴하듯이 하면 된다.*/
			List<MemberDTO> resultList3 =em.createQuery("select new jpashop.home.domain.MemberDTO(m.username, m.age) from Member m ", MemberDTO.class).getResultList();
			MemberDTO memberDTO=resultList3.get(0);
			System.out.println("방법 2 username = " +memberDTO.getUsername());
			System.out.println("방법 2 age = " +memberDTO.getAge());

 

 


• 단순 값을 DTO로 바로 조회

 

SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m


• 패키지 명을 포함한 전체 클래스 명 입력


• 순서와 타입이 일치하는 생성자 필요

 

 

 

 

 

 

 

 

38.  페이징

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21721&tab=curriculum

 

 

JPA는 페이징을 다음 두 API로 추상화

setFirstResult(int startPosition) : 조회 시작 위치 (0부터 시작)


setMaxResults(int maxResult) : 조회할 데이터 수

 

 

 

페이징 API 예시

 

//페이징 쿼리
 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();

 

 

페이징 API - 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 ?, ?

 

 

페이징 API - 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_ > ?

 

package jpashop.jpql;


import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import jpashop.home.domain.Member;

public class JpaMainPaging {
	public static void main(String[] args) {
		EntityManagerFactory emf=Persistence.createEntityManagerFactory("hello");
		
		EntityManager em=emf.createEntityManager();
		
		//JPA 의 모든 데이터 변경은  트랜잭션 안에서 실행 되어야 한다.
		EntityTransaction tx=em.getTransaction();
		tx.begin();
			
		try {
			
			for(int i=0; i<100;  i++) {
				Member member=new Member();
				member.setUsername("member"+i);
				member.setAge(i);
				em.persist(member);	
			}
			
			em.flush();
			em.clear();
			
			List<Member> result =em.createQuery("select m from Member m order by m.age desc", Member.class)
					.setFirstResult(1)
					.setMaxResults(10)
					.getResultList();
			
			System.out.println("result.size = "+result.size());
			for(Member meber1: result) {
				System.out.println("meber = "+meber1);
			}
			
			
			tx.commit();
		}catch(Exception e) {
			tx.rollback();
			e.printStackTrace();
		}finally {
			em.close();
		}
	
		
		emf.close();	
	}
	

}

 

Hibernate: 
    /* select
        m 
    from
        Member m 
    order by
        m.age desc */ select
            member0_.MEMBER_ID as member_i1_0_,
            member0_.age as age2_0_,
            member0_.TEAM_ID as team_id4_0_,
            member0_.USERNAME as username3_0_ 
        from
            Member member0_ 
        order by
            member0_.age desc limit ? offset ?
result.size = 10
meber = Member(id=99, username=member98, age=98, team=null)
meber = Member(id=98, username=member97, age=97, team=null)
meber = Member(id=97, username=member96, age=96, team=null)
meber = Member(id=96, username=member95, age=95, team=null)
meber = Member(id=95, username=member94, age=94, team=null)
meber = Member(id=94, username=member93, age=93, team=null)
meber = Member(id=93, username=member92, age=92, team=null)
meber = Member(id=92, username=member91, age=91, team=null)
meber = Member(id=91, username=member90, age=90, team=null)
meber = Member(id=90, username=member89, age=89, team=null)

 

 

 

 

 

 

 

 

39.  조인

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21722&tab=curriculum

 

 

• 내부 조인:

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

 

 

 

 

조인 - ON 절

 

• ON절을 활용한 조인(JPA 2.1부터 지원)


• 1. 조인 대상 필터링
• 2. 연관관계 없는 엔티티 외부 조인(하이버네이트 5.1부터)

 

Team

package jpashop.home.domain;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import lombok.Getter;
import lombok.Setter;

@Entity
@Getter
@Setter
public class Team {

	@Id
	@GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;

	private String name;

	@OneToMany(mappedBy = "team")
	private List<Member> members = new ArrayList<Member>();

}

 

Member

package jpashop.home.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Entity
@Getter
@Setter
@ToString
public class Member {

	@Id
	@GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;

	@Column(name = "USERNAME")
	private String username;

	private int age;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "TEAM_ID")
	private Team team;

	public void changeTeam(Team team) {
		this.team=team;
		team.getMembers().add(this);
	}
	
}

 

Main조인

package jpashop.jpql;


import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import jpashop.home.domain.Member;
import jpashop.home.domain.MemberDTO;
import jpashop.home.domain.Team;

public class Main조인 {
	public static void main(String[] args) {
		EntityManagerFactory emf=Persistence.createEntityManagerFactory("hello");
		
		EntityManager em=emf.createEntityManager();
		
		//JPA 의 모든 데이터 변경은  트랜잭션 안에서 실행 되어야 한다.
		EntityTransaction tx=em.getTransaction();
		tx.begin();
			
		try {
			
			Team team=new Team();
			team.setName("teamA");
			em.persist(team);
			
			Member member=new Member();
			member.setUsername("member1");
			member.setAge(10);
			member.changeTeam(team);
			
			em.persist(member);	
	
			em.flush();
			em.clear();
			
			String query="select m  from Member m LEFT join m.team t on t.name='A' ";
			List<Member> result =em.createQuery(query, Member.class).getResultList();
				
			System.out.println(" reuslt : "+result.size());
			tx.commit();
		}catch(Exception e) {
			tx.rollback();
			e.printStackTrace();
		}finally {
			em.close();
		}
	
		
		emf.close();	
	}
	

}

 

 

 

1. 조인 대상 필터링

 

JPQL:
SELECT m, t FROM Member m LEFT JOIN m.team t on t.name = 'A'

 

 

SQL:
SELECT m.*, t.* FROM
Member m LEFT JOIN Team t ON m.TEAM_ID=t.id and t.name='A' 

 

 

 

 

 

2. 연관관계 없는 엔티티 외부 조인

 

• 예) 회원의 이름과 팀의 이름이 같은 대상 외부 조인

JPQL:
SELECT m, t FROM
Member m LEFT JOIN Team t on m.username = t.name

 

SQL:
SELECT m.*, t.* FROM
Member m LEFT JOIN Team t ON m.username = t.name

 

 

 

 

 

 

 

 

 

 

 

40. 서브 쿼리

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21723&tab=curriculum

 

• 나이가 평균보다 많은 회원

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

 

 

 

 

서브 쿼리 지원 함수

 

[NOT] EXISTS (subquery):  서브쿼리에 결과가 존재하면 참


{ALL | ANY | SOME} (subquery)


•  ALL  모두 만족하면 참


ANY, SOME:    같은 의미, 조건을 하나라도 만족하면 참


[NOT] IN (subquery):   서브쿼리의 결과 중 하나라도 같은 것이 있으면 

 

 

 

 

 

서브 쿼리 - 예

 

팀A 소속인 회원  exists

select m from Member m
where exists (select t from m.team t where t.name = ‘팀A')

 

전체 상품 각각의 재고보다 주문량이 많은 주문들  ALL

select o from Order o
where o.orderAmount > ALL (select p.stockAmount from Product p)

 

어떤 팀이든 팀에 소속된 회원    ANY

select m from Member m
where m.team = ANY (select t from Team t)

 

 

 

JPA 서브 쿼리 한계

 

• JPA는 WHERE, HAVING 절에서만 서브 쿼리 사용 가능
• SELECT 절도 가능(하이버네이트에서 지원)
• FROM 절의 서브 쿼리는 현재 JPQL에서 불가능
• 조인으로 풀 수 있으면 풀어서 해결

 

 

하이버네이트6 변경 사항


• 하이버네이트6 부터는 FROM 절의 서브쿼리를 지원합니다.


• 참고 링크
https://in.relation.to/2022/06/24/hibernate-orm-61-features/

 

 

 

 

 

 

 

41. JPQL 타입 표현과 기타식

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21724&tab=curriculum

 

 

JPQL 타입 표현


문자: ‘HELLO’, ‘She’’s’


숫자:  10L(Long),  10D(Double),  10F(Float)


Boolean: TRUE, FALSE


ENUM: jpabook.MemberType.Admin (패키지명 포함)

 

package jpashop.home;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import jpashop.home.domain.Book;
import jpashop.home.domain.Item;

public class JPQL타입표현과기타식 {
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

		EntityManager em = emf.createEntityManager();

		// JPA 의 모든 데이터 변경은 트랜잭션 안에서 실행 되어야 한다.
		EntityTransaction tx = em.getTransaction();
		tx.begin();

		try {


			Book book = new Book();
			book.setPrice(10000);
			book.setName("JPA");
			book.setIsbn("d33523");
			book.setAuthor("김영한2");
			book.setStockQuantity(10);

			em.persist(book);

			System.out.println("===============================");
			em.createQuery("select i from Item  i  where type(i) = Book ", Item.class).getResultList();
			System.out.println("===============================");

			tx.commit();

		} catch (Exception e) {
			tx.rollback();
		} finally {
			em.close();
		}
		emf.close();
	}

}

 


엔티티 타입: TYPE(m) = Member (상속 관계에서 사용)
 

 


JPQL 기타


• SQL과 문법이 같은 식
• EXISTS, IN
• AND, OR, NOT
• =, >, >=, <, <=, <>
• BETWEEN, LIKE, IS NULL

 

 

 

 

 

 

 

 

42. 조건식(CASE 등등)

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21725&tab=curriculum

 

기본 CASE 식

 

select
 case when m.age <= 10 then '학생요금'
 when m.age >= 60 then '경로요금'
 else '일반요금'
 end
from Member m

 

 

단순 CASE 식

select
 case t.name
 when '팀A' then '인센티브110%'
 when '팀B' then '인센티브120%'
 else '인센티브105%'
 end
from Team t

 

 

 

조건식 - CASE 식

 

COALESCE

사용자 이름이 없으면 이름 없는 회원을 반환

select coalesce(m.username,'이름 없는 회원') from Member m

 

 

NULLIF

사용자 이름이 ‘관리자’면 null을 반환하고 나머지는 본인의 이름을 반환

select NULLIF(m.username, '관리자') from Member m


 

 

 

 

 

 

 

 

 

43. JPQL 함수

 

강의 :

https://www.inflearn.com/course/lecture?courseSlug=ORM-JPA-Basic&unitId=21726&tab=curriculum

 

 

• CONCAT


• SUBSTRING


• TRIM


• LOWER, UPPER


• LENGTH


• LOCATE


• ABS, SQRT, MOD


• SIZE, INDEX(JPA 용도)

 

 

사용자 정의 함수 호출

 

• 하이버네이트는 사용전 방언에 추가해야 한다.
• 사용하는 DB 방언을 상속받고, 사용자 정의 함수를 등록한 다.
 

select function('group_concat', i.name) from Item i

 

설정 방법

1.MyH2Dialect

package jpashop.home;

import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StandardBasicTypes;

public class MyH2Dialect extends H2Dialect {

	public MyH2Dialect() {
		registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
	}
	
	
}

 

 

 

persistence.xml

 

~
		<!-- 	<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /> -->
			<property name="hibernate.dialect" value="jpashop.home.MyH2Dialect" />
				 


~

 

JPQL기본함수

package jpashop.home;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import jpashop.home.domain.Member;

public class JPQL기본함수 {
	public static void main(String[] args) {
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

		EntityManager em = emf.createEntityManager();

		// JPA 의 모든 데이터 변경은 트랜잭션 안에서 실행 되어야 한다.
		EntityTransaction tx = em.getTransaction();
		tx.begin();

		try {
			Member member1 =new Member();
			member1.setName("관리자1");
			em.persist(member1);

			Member member2 =new Member();
			member2.setName("관리자2");
			em.persist(member2);
			
			em.flush();
			em.clear();
			
			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 = " + s);
			}
			
			tx.commit();

		} catch (Exception e) {
			tx.rollback();
		} finally {
			em.close();
		}
		emf.close();
	}

}

 

    /* select
        function('group_concat',
        m.name ) 
    FROM
        Member m */ select
            group_concat(member0_.name) as col_0_0_ 
        from
            Member member0_
s = 관리자1,관리자2

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

부귀는 요새(要塞)이며, 빈곤은 폐허이다. -탈무드

댓글 ( 4)

댓글 남기기

작성