์คํ๋ง๊ณผ JPA๋ฅผ ์ด์ฉํ ์น๊ฐ๋ฐ_JPQL
๐คJPQL๋?(Java Persistence Query Language)
- ๊ฐ์ฒด์งํฅ ์ฟผ๋ฆฌ!
- JPQL์ ํ ์ด๋ธ์ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑ
- JPQL๋ก ์คํํ ์ฟผ๋ฆฌ๋ ๊ฒฐ๊ตญ SQL๋ก ๋ณํ๋์ด ์คํ
- ๋ฐ๋ผ์ ์คํ๋๋ SQL ๋ก๊น ํ์ฌ ํ์ธํ๋ ์์ ์ด ํ์
- JPA์์ ๊ด๋ฆฌ๋๋ ์ํฐํฐ์ ๋ํ SQL์ ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ด์ง๋ง JPQL์ ์ฆ์ ์คํ ๋จ
JPA๊ฐ ์๋๋ฐ๋ JPQL์ ์ฌ์ฉํด์ผํ๋์?
โก๏ธJPA๋ก๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ํ ๋ ์กฐ๊ฑด์ ํ๊ณ๊ฐ ์๊ธฐ ๋๋ฌธ์ JPQL์ ์ฌ์ฉํด์ผ ํฉ๋๋ค!
Ex) 20๋ ์ด์์ธ ๋จ์ฑ ์ค์์, ๊ตฌ๋งค๋ฅผ 2๋ฒ ์ด์ ํ ๊ณ ๊ฐ๋ค์ ๋์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์กฐํํด์ผํ ๋
โก๏ธ์ฆ, SQL๊ด์ ์์ Where์ ์ด ํ์ํ ์๊ฐ์ JPQL์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
Selection
- Selection – The FROM clause
- FROM ์ ์ select ๋์์ด ๋๋ ์ํฐํฐ๋ฅผ ์ง์ ํ๊ธฐ ์ํด ์ฌ์ฉ
SELECT a FROM Author (AS) a
- AS๋ ์๋ต ๊ฐ๋ฅ
- ์ ์์์์ Author๋ DB ํ ์ด๋ธ์ ์๋ฏธํ๋ ๊ฒ์ด ์๋ ์ํฐํฐ๋ฅผ ์๋ฏธ
- ๋ฐ๋์ ๋ณ์นญ์ ๋ช ์ํด์ผ ํจ. ์ ์์์์๋ a์ ํด๋น
- persist๊ฐ INSERT๋ฌธ์ ๋์ ํจ
Types of JPA Queries: Query์ ์ข ๋ฅ
- TypedQuery
- ์ฟผ๋ฆฌ ์คํ์ ๊ฒฐ๊ณผ๋ก ๋ฐํ๋ ํ์ ์ ์๊ณ ์์ ๋
- ์ถ๊ฐ์ ์ธ ํ๋ณํ์ด ์๊ณ ์ ์ฐํ๊ณ ์ฌ์ด ํ ์คํธ๋ฅผ ์ ๊ณต
โก๏ธJPQL์ฟผ๋ฆฌ๋ฅผ ์ ๊ณ , UserEntity.class๋ฅผ ๋ฐํ(=Return type)ํ๋ค๋ ๊ฒ์ ๋ช ์ํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ TypedQuery์ ์ง๋ค๋ฆญํ์ ์ UserEntity๋ฅผ ์ง์ ํด์ฃผ๋ฉด ๋๋ค!
+) ์์ JPQL์ ์ฌ์ฉ์๊ฐ ์ง์ ํ id๊ฐ์ where์ ๋ก ๊ฐ์ ธ์ค๊ฒ ๋ค๋ ๋ป.
- NamedQuery
- ์ํฐํฐ์ ์คํ๋ JPQL๊ณผ ๊ทธ ์ด๋ฆ์ ๋ช ์ํ์ฌ ์ง๊ด์ ์ผ๋ก ์ดํด
โก๏ธ์ด๋ฆ ๊ทธ๋๋ก name์ด ์๋ ์ฟผ๋ฆฌ๋ผ์ Query๋ง ๋ณด๋ฉด ์ฝ๊ธฐ ์ ๊น์ง ์ด๋ค ์ฟผ๋ฆฌ์ธ์ง ๋ชจ๋ฅด์ง๋ง, name์ด ์์ผ๋ฉด ์ดํด๋ UP!!
- NativeQuery
- ์๋ Native๋ผ๋ ์ด๋ฆ์ฒ๋ผ ๊ทธ๋ฅ SQL์ฟผ๋ฆฌ
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ JPQL์ ๊ตฌ๋ฌธ์ ์ ์ฝ ์์ด ๋์ DB์ ๊ณง ๋ฐ๋ก SQL์คํ๊ฐ๋ฅ
- JPQL์ด๋ JPA์ ๊ด๋ฆฌ๋ฅผ ๋ฒ์ด๋๋ฏ๋ก ์ด์์ฑ์ด ๋จ์ด์ง ์ ์์
- ๊ทธ๋์ NativeQuery๋ ์ตํ์ ์๋จ์ผ๋ก ์๊ฐ..!
- NativeQuery ๋ ๋ ธ๋๋ฐ๋ ๊ธฐ์กด JPA๋ณด๋ค ์ฑ๋ฅ์ด ์ข์ผ๋ฉด JPA์ ์ฐ๊ด๊ด๊ณ ๋ฑ์ ์๋ชป ์ฌ์ฉํ๋ค๋ ๋ป์ด๊ธฐ๋ ํ๋ค
๐ถ์์ฑํ JPQL์ ์คํํ๋ ค๋ฉด ์ฟผ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค!
- ํ์ ์ ๋ช ์ํ ์ ์์ ๋
TypedQuery<String> query = em.createQuery("SELECT p.name from Person p", String.class);
List<String> resultList = query.getResultList();
โก๏ธp.name์ ๋น์ฐํ Stringํ์ ์ผ๋ก ๋ฐํ๋ ๊ฒ์ด๋ฏ๋ก ๋ฐํ ํ์ ๊ณผ ์ง๋ค๋ฆญํ์ ์ String.class๋ฅผ ์ ์ด์ฃผ๋ฉด ๋๋ค.
โ์ JPQL์ ์ ์ SQL์ "SELECT NAME FROM PERSON"๊ณผ ๊ฐ๋ค!
- ํ์ ์ ๋ช ์ํ ์ ์์ ๋
Query query = em.createQuery("SELECT p.name, p.age from Person p");
List resultList = query.getResultList();
for(Object o: resultList){
Object[] result = (Object[]) o; //๊ฒฐ๊ณผ๊ฐ ๋ ์ด์์ด๋ฉด Object[] ๋ฐํ, ํ๋๋ฉด Object ๋ฐํ
System.out.println("name = " + result[0]);
System.out.println("age = " + result[1]);
}
โก๏ธp.name์ String์ด๊ณ p.age๋ intํ์ ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ด ๊ฒฝ์ฐ์๋ ์๋ฐ์์ ์ต์์ ๊ณ์ธต์ธ Object๋ฅผ ๋ฐํํ๋ค!
๋ํ, ๊ฒฐ๊ณผ๊ฐ์ด ๋๊ฐ ์ด์์ด๊ธฐ ๋๋ฌธ์ List []์ผ๋ก ๋ฐํํ๋ค.
๋ํ์ ์ธ JPQL์ ๊ธฐ๋ฅ = "getResult"
- query.getResultList()
- ๊ฒฐ๊ณผ๊ฐ ํ๋ ์ด์์ธ ๊ฒฝ์ฐ, ๋ฆฌ์คํธ๋ฅผ ๋ฐํ
- ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด null๋ฐํ
- query.getSingleResult()
- ์ผ์นํ๋ ํ๋์ ์ํฐํฐ๋ฅผ ๋ฐํ
- ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ ํ ๊ฐ๋ฅผ ์ด๊ณผํ๋ฉด ์์ธ ๋ฐ์
- ์คํ๋ง ๋ฐ์ดํฐ JPA์์๋ ํ ๊ฐ๋ฅผ ์ด๊ณผํ ๋ null ๋ฐํ
โก๏ธgetSingleResult๊ฐ ์กฐ๊ธ ๋ ์๊ฒฉํ๋ค๊ณ ๋ณผ ์ ์์!
์์ : ๋ฐํ ํ์ ์ ์ ๋
@Entity
public class Person {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "PERSON_ID")
private int id;
private String name;
private int age;
@OneToMany(mappedBy = "person", cascade = CascadeType.REMOVE)
private List<Address> addresses = new ArrayList<Address>();
...
@Entity
public class Address {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String street;
private String city;
private String zipCode;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PERSON_ID")
private Person person;
...
package study;
import javax.persistence.*;
import java.util.List;
public class Main {
public static void main(String[] args){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("playground");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
try{
tx.begin();
Address address1 = new Address();
address1.setCity("city1");
address1.setStreet("street1");
address1.setZipCode("zipCode1");
Address address2 = new Address();
address2.setCity("city1");
address2.setStreet("street1");
address2.setZipCode("zipCode1");
Person person = new Person();
person.setName("kim");
person.setAge(20);
address1.setPerson(person); //์ฐ๊ด๊ด๊ณ ์ฃผ์
address2.setPerson(person);
person.getAddresses().add(address1);
person.getAddresses().add(address2);
em.persist(person);
em.persist(address1);
em.persist(address2);
em.flush();
em.clear();
----์ฌ๊ธฐ์๋ถํฐ JPQL์ฟผ๋ฆฌ!!-----
TypedQuery<Person> query =
em.createQuery("SELECT p FROM Person AS p", Person.class);
List<Person> resultList = query.getResultList();
resultList.stream().forEach(v-> System.out.println("v = " + v));
tx.commit();
}catch (Exception e){
tx.rollback();
}finally {
em.close();
}
}
}
โก๏ธ์คํํ๋ฉด addresses ๊ฐ์ด ์ด์ํ๊ฒ ๋์ค๋๋ฐ, ์ด๋ Person์์ @OneToMany๊ฐ fetch์ ๊ธฐ๋ณธ ๊ฐ์ด LAZY์ด๊ธฐ ๋๋ฌธ!
์์ฉversion : ๋ฐํ ํ์ ์ ๋ชจ๋ฅผ ๋
Query query = em.createQuery(("SELECT p.name, p.age FROM Person p"));
List resultList = query.getResultList();
for(Object o:resultList){
Object[] result = (Object[]) o;
System.out.println("result[0]= " + result[0]);
System.out.println("result[1]= " + result[1]);
}
โก๏ธ๋ฐํํ์ ์ ๋ชจ๋ฅผ ๊ฒฝ์ฐ return ํ์ ์ ์ง์ ํด์ฃผ์ง ์๊ณ ์ต์์ ๊ณ์ธต์ธ Object๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํฐ ์ฐจ์ด์ ์ด๋ค!
โList ํ์ ์ด ์ ์ฅ๋ ๋๋ [kim, 20] ์ด๋ฐ ์์ผ๋ก ์ ์ฅ๋๋ค!