[JPA] JPQL ๋ฌธ๋ฒ 1 - ๊ธฐ๋ณธ ๋ฌธ๋ฒ, ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ, ํ๋ก์ ์ , ํ์ด์ง
by rlaehddnd0422SQL์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ๋์์ผ๋ก ํ๋ ์กฐํ ์ฟผ๋ฆฌ ์๋ค๋ฉด JPQL์ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์กฐํํ๋ ๊ฐ์ฒด ์งํฅ ์ฟผ๋ฆฌ์ ๋๋ค.
JPQL์ ๋ฌธ๋ฒ์ SQL๊ณผ ๋น์ทํ๊ณ , ANSI ํ์ค SQL์ด ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ์ ์ฌํ๊ฒ ์ง์ํฉ๋๋ค.
SQL์ ์ถ์ํํ ๋๋ถ์ ํน์ SQL์ ์์กดํ์ง ์์ ๋๋ถ๋ถ์ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฉํ ์ ์์ต๋๋ค.
JPQL์ ๊ฒฐ๊ตญ ๊ฐ์ฒด ์งํฅ์ ์ธ ์ฟผ๋ฆฌ์ผ ๋ฟ, ์คํ๋ ๋ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ ๋์๋ SQL๋ก ๋ณํ๋์ด ์ ๋ฌ๋ฉ๋๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ๊ณผ ์ฟผ๋ฆฌ API
JPQL๋ SQL๊ณผ ๋น์ทํ๊ฒ SELECT, UPDATE, DELETE๋ฌธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
INSERT๋ฌธ์ em.persist๋ฅผ ์ฌ์ฉํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ์ง์ ์ ์ผ๋ก JPQL์๋ INSERT๋ฌธ์ด ์ง์ ์ ์ผ๋ก ํฌํจ๋์ด ์์ง ์์ต๋๋ค.
SELECT ๋ฌธ
select ๋ฌธ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํฉ๋๋ค.
SELECT m
FROM Member AS m
where m.username='hello'
- ์ํฐํฐ์ ์์ฑ์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํฉ๋๋ค. (Member, username)
- ์ํฐํฐ ์ด๋ฆ
- ์ JPQL์์ ์ฌ์ฉํ Member๋ ํด๋์ค๋ช X ์ํฐํฐ๋ช O
- ์๋ฐ ์ง์์ ์ํฐํฐ๋ช ์ ์ง์ (@Entity(name="~")) ํ์ง ์์ผ๋ฉด ํด๋์ค ์ด๋ฆ์ผ๋ก ์๋ ์ง์ ๋ฉ๋๋ค.
- ๊ธฐ๋ณธ๊ฐ์ธ ํด๋์ค๋ช ์ ์ํฐํฐ๋ช ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค.
- ๋ณ์นญ : Member AS m์ ๋ณด๋ฉด Member์ m์ด๋ผ๋ ๋ณ์นญ์ ๋ถ์ฌํ์ต๋๋ค. JPQL์์๋ ๋ณ์นญ์ ํ์์ ์ผ๋ก ์ฌ์ฉํด์ผ ํฉ๋๋ค.
- AS๋ ์๋ต ๊ฐ๋ฅ. ๋ฐ๋ผ์ Member m์ผ๋ก ์์ฑํด๋ ์ข์ต๋๋ค.
์์ฑํ JPQL๋ฌธ์ ์คํํ๋ ค๋ฉด ์ฟผ๋ฆฌ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ฟผ๋ฆฌ ๊ฐ์ฒด๋ TypeQuery์ Query ๊ฐ์ฒด๊ฐ ์์ต๋๋ค.
- TypeQuery : ๋ฐํํ ํ์ ์ ๋ช ํํ๊ฒ ์ง์ ํ ์ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ
- Query : ๋ฐํ ํ์ ์ ๋ช ํํ๊ฒ ์ง์ ํ ์ ์๋ ๊ฒฝ์ฐ ์ฌ์ฉ
TypeQuery
// ๋ฐํ ํ์
์ ๋ช
ํํ๊ฒ ์ง์ ๊ฐ๋ฅํ ๊ฒฝ์ฐ
TypedQuery<Member> query = em.createQuery("SELECT m FROM Member m", Member.class);
List<Member> resultList = query.getResultList();
for (Member member : resultList) {
System.out.println("member = " + member);
}
- ์กฐํ ๋์์ด Member ์ํฐํฐ์ด๋ฏ๋ก ์กฐํ ๋์ ํ์ ์ด ๋ช ํํฉ๋๋ค. ์ด๋๋ TypeQuery๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
Query
Query query = em.createQuery("SELECT m.id, m.name FROM Member m");
List resultList = query.getResultList();
for (Object o : resultList) {
Object[] result = (Object[]) o; // ๊ฒฐ๊ณผ๊ฐ ๋ ์ด์์ธ ๊ฒฝ์ฐ
System.out.println("id = " + result[0]);
System.out.println("name = " + result[1]);
}
- ์กฐํ ๋์์ด String ํ์ ์ธ ์ด๋ฆ๊ณผ Integer ํ์ ์ธ ๋์ด์ด๋ฏ๋ก ์กฐํ ๋์ ํ์ ์ด ๋ช ํํ์ง ์์ต๋๋ค.
- ์ฌ๋ฌ ์ํฐํฐ๋ ์ปฌ๋ผ์ ์ ํํ ๋๋ ๋ฐํ ํ์ ์ด ๋ช ํํ์ง ์๊ธฐ ๋๋ฌธ์ Query ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
- ์กฐํ ๋์์ด ๋ ์ด์์ธ ๊ฒฝ์ฐ Object[]๋ฅผ ๋ฐํํ๊ณ , ์กฐํ ๋์์ด ํ๋์ธ ๊ฒฝ์ฐ Object๋ฅผ ๋ฐํํฉ๋๋ค.
query.getResultList() : ์ฟผ๋ฆฌ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ฆฌ์คํธ ํํ๋ก ๋ฆฌํด, ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด ๋น ์ปฌ๋ ์ ๋ฆฌํดํฉ๋๋ค.
query.getSingleResult() : ๊ฒฐ๊ณผ๊ฐ ์ ํํ ํ๋์ผ ๋ ๊ฒฐ๊ณผ ๋ฆฌํด, ๋ง์ฝ ๊ฒฐ๊ณผ๊ฐ ์๊ฑฐ๋ ๊ฒฐ๊ณผ๊ฐ ์ฌ๋ฌ๊ฐ์ธ ๊ฒฝ์ฐ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ
JDBC๋ ์์น ๊ธฐ๋ฐ (?๋ฅผ ์ฌ์ฉํ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ) ๋ฐ์ธ๋ฉ๋ง ์ง์ํ์ง๋ง JPQL์ ์ด๋ฆ ๊ธฐ์ค ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ๋ ์ง์ํฉ๋๋ค.
์์น ๊ธฐ๋ฐ ํ๋ผ๋ฏธํฐ
List<Member> members = em.createQuery("SELECT m FROM Member m where m.name = ?1", Member.class)
.setParameter(1, 'kim')
.getResultList();
for (Member member : members) {
System.out.println("member = " + member);
}
โป JPQL API๋ ๋๋ถ๋ถ ๋ฉ์๋ ์ฒด์ธ ๋ฐฉ์์ผ๋ก ์ค๊ณ๋์ด ์์ด ์ฐ์ํด์ ์์ฑํ ์ ์์ต๋๋ค.
์ด๋ฆ ๊ธฐ๋ฐ ํ๋ผ๋ฏธํฐ
List<Member> members = em.createQuery("SELECT m FROM Member m where m.name := username", Member.class)
.setParameter("username", 'kim')
.getResultList();
for (Member member : members) {
System.out.println("member = " + member);
}
์ด๋ฆ ๊ธฐ๋ฐ ํ๋ผ๋ฏธํฐ๋ ํ๋ผ๋ฏธํฐ ์ด๋ฆ์ผ๋ก ๊ตฌ๋ถํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ฑํธ ์์ :๋ฅผ ์ฌ์ฉํฉ๋๋ค.
+ ์ง์ ๋ฌธ์๋ฅผ ๋ํด JPQL๋ฌธ์ ๋ง๋๋ ๋ฐฉ์์ SQL ์ธ์ ์ ๊ณต๊ฒฉ์ ์๋นํ ์ทจ์ฝํฉ๋๋ค.
์๋ฅผ๋ค์ด ์๋์ ๊ฐ์ JPQL๋ฌธ์ ๋ง๋ค์๋ค๊ณ ๊ฐ์ ํด๋ด ์๋ค.
String query = "SELECT * FROM Member m WHERE m.username = '" + username + "' AND m.password = '" + password + "'";
์ ์์ ์ธ ์ ๋ ฅ์ ๊ฒฝ์ฐ ์คํ๋๋ JPQL
SELECT * FROM Member m WHERE username = 'john' AND password = 'secret'
์ ์์ ์ธ ์ ๋ ฅ์ ๊ฒฝ์ฐ ์คํ๋๋ JPQL
SELECT * FROM Member m WHERE username = '' OR '1'='1' AND password = '' OR '1'='1'
์ด ๊ฒฝ์ฐ, '1'='1' ์กฐ๊ฑด์ด ํญ์ ์ฐธ์ด ๋๊ธฐ ๋๋ฌธ์ ์ ์์ ์ธ ์ฌ์ฉ์๋ ๋ก๊ทธ์ธ ์ ์ฐจ๋ฅผ ์ฐํํ๊ณ ๋ชจ๋ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ์ก์ธ์คํ ์ ์์ ์ ์์ต๋๋ค.
๋ฐ๋ผ์ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ ๋ฐฉ์์ ์ฌ์ฉํ๋, ์ข ๋ ๋ช ํํ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ ๋ฐฉ์์ธ ์ด๋ฆ ๊ธฐ๋ฐ ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ ๋ฐฉ์์ ์ฌ์ฉํ๋๋ก ํฉ์๋ค.
ํ๋ก์ ์
select์ ์ ์กฐํํ ๋์์ ์ง์ ํ๋ ๊ฒ์ ํ๋ก์ ์ ์ด๋ผ๊ณ ํฉ๋๋ค.
ํ๋ก์ ์ ์๋ ์ํฐํฐ ๋ฟ๋ง ์๋๋ผ, ์๋ฒ ๋๋ ํ์ , ์ค์นผ๋ผ ํ์ ๋ํ ์ง์ ํ ์ ์์ต๋๋ค.
'์ค์นผ๋ผ ํ์ '์ด๋?
: ์ซ์, ๋ฌธ์ ๋ฑ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์
์ํฐํฐ ํ๋ก์ ์
SELECT m FROM Member m
SELECT m.username FROM Member m
์กฐํํ ์ํฐํฐ๋ ์์์ฑ ์ปจํ ์คํธ์์ ๊ด๋ฆฌ๋ฉ๋๋ค.
์๋ฒ ๋๋ ํ์ ํ๋ก์ ์
์๋ฒ ๋๋ ํ์ ์ด๋?
JPQL์์ ์๋ฒ ๋๋ ํ์ ์ ์ํฐํฐ์ ๊ฑฐ์ ๋น์ทํ๊ฒ ์ฌ์ฉ๋์ง๋ง, ํ์ง๋ง ํ ๊ฐ์ง ์ ์ฝ์ด ์์ต๋๋ค.
๋น์ฐํ ์๊ธฐ์ง๋ง, ์๋ฒ ๋๋ ํ์ ์ ์กฐํ์ ์์์ ์ด ๋ ์๊ฐ ์์ต๋๋ค. ์์์ ์ ๋ฐ๋์ ์ํฐํฐ๋ฅผ ํตํด์ ์ ๊ทผํด์ผ ํฉ๋๋ค.
์๋ชป๋ ์์
SELECT a FROM Address a
์ฌ๋ฐ๋ฅธ ์ฌ์ฉ ์์
TypedQuery<Address> query = em.createQuery("SELECT o.address FROM Orders o", Address.class);
List<Address> resultList = query.getResultList();
์๋ฒ ๋๋ ํ์ ์ ์ํฐํฐ ํ์ ์ด ์๋ ๊ฐ ํ์ ์ด๊ธฐ ๋๋ฌธ์ ์กฐํํ ์๋ฒ ๋๋ ํ์ ์ ์์์ฑ ์ปจํ ์คํธ์์ ๊ด๋ฆฌ๋์ง ์์ต๋๋ค.
์ค์นผ๋ผ ํ์ ํ๋ก์ ์
์ซ์, ๋ฌธ์, ๋ ์ง์ ๊ฐ์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ํ์ ๋ค์ ์ค์นผ๋ผ ํ์ ์ด๋ผ๊ณ ํฉ๋๋ค. ์๋ฅผ๋ค์ด ์ ์ฒด ํ์์ ์ด๋ฆ์ ์กฐํํ๊ณ ์ถ์ ๋ ๋ค์ ์ฒ๋ผ ์ฟผ๋ฆฌํ๋ฉด ๋ฉ๋๋ค.
TypedQuery<String> query = em.createQuery("SELECT m.name FROM Member m", String.class);
List<String> resultList = query.getResultList();
์ฌ๋ฌ ๊ฐ ํ๋ก์ ์
์ํฐํฐ๋ฅผ ๋์์ผ๋ก ์กฐํํ๋ฉด ํธ๋ฆฌํ๊ฒ ์ง๋ง, ๊ผญ ํ์ํ ๋ฐ์ดํฐ๋ค๋ง ์ ํํด์ ์กฐํํด์ผ ํ ๋๋ ์์ต๋๋ค.
ํ๋ก์ ์ ์ ์ฌ๋ฌ๊ฐ์ ์ ํํ๋ฉด TypeQuery๋ฅผ ์ฌ์ฉํ ์ ์๊ณ Query๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
List<Object[]> resultList = em.createQuery("SELECT m.name, m.age FROM Member m")
.getResultList();
for (Object[] row : resultList) {
String username = (String) row[0];
Integer age = (Integer) row[1];
System.out.println("username = " + username);
System.out.println("age = " + age);
}
์ค์ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ์์๋ Object[]๋ฅผ ์ฌ์ฉํ์ง ์๊ณ DTO ๋ก ๋ณํํด์ ์ฌ์ฉํฉ๋๋ค.
List<Object[]> resultList = em.createQuery("SELECT m.name, m.age FROM Member m")
.getResultList();
List<MemberDto> memberDTOs = new ArrayList<MemberDto>();
for (Object[] row : resultList) {
MemberDto memberDto = new MemberDto((String) row[0], (Integer) row[1]);
memberDtos.add(memberDto);
}
- DTO ๋ณํ ์์ ์ ์ถ๊ฐ๋ก ์ํํฉ๋๋ค.
- ๊ฐ์ฒด ๋ณํ ์์ ๋ ๊ท์ฐฎ๊ฒ for๋ฌธ์ผ๋ก ์์ฑํ์ง ์๊ณ , new ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ JPQL ํ๋๋ก ํ์ณ์ ๋ณํํ ์ ์์ต๋๋ค.
TypedQuery<MemberDto> query = em.createQuery("SELECT new domain.MemberDto(m.name, m.age) FROM Member m", MemberDto.class);
List<MemberDto> resultList = query.getResultList();
- new ๋ช ๋ น์ด ์ฌ์ฉ์ ํจํค์ง ๋ช ์ ํฌํจํ ์ ์ฒด ํด๋์ค๋ช ์ ์ ๋ ฅํด์ผ ํ๊ณ
- ์์์ ํ์ ์ด ์ผ์นํ๋ ์์ฑ์๊ฐ ํ์ํฉ๋๋ค.
ํ์ด์ง ์ฒ๋ฆฌ ๋ฉ์๋
ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ ํ์ด์ง ๋จ์๋ก ๋๋์ด์ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง๋ค ํ์ด์ง์ ์ฒ๋ฆฌํ๋ SQL๋ฌธ๋ฒ์ด ๋ค๋ฅด์ง๋ง, JPA๋ ํ์ด์ง์ ๋ค์ ๋ API๋ก ์ถ์ํ ํด๋์์ต๋๋ค.
- setFirstResult(int startPosition) : ์กฐํ ์์ ์์น ( 0๋ถํฐ ์์ )
- setMaxResults(int maxResult) : ์กฐํํ ๋ฐ์ดํฐ ์
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > Spring Data JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] JPQL ๋ฌธ๋ฒ 3 - ๊ฒฝ๋ก ํํ์, ์๋ธ ์ฟผ๋ฆฌ, ์กฐ๊ฑด์ (0) | 2023.05.10 |
---|---|
[JPA] JPQL ๋ฌธ๋ฒ 2 - ์งํฉ ๋ฐ ์ ๋ ฌ, ์กฐ์ธ, ํ์น ์กฐ์ธ (0) | 2023.05.09 |
[JPA] ๊ฐ ํ์ - ์๋ฒ ๋๋ ๊ฐ ํ์ , ์ปฌ๋ ์ ๊ฐ ํ์ (0) | 2023.05.08 |
[JPA] ์์์ฑ ์ ์ด by Cascade ์ต์ (0) | 2023.05.05 |
[JPA] ํ๋ก์(Proxy)์ ์ง์ฐ๋ก๋ฉ(Lazy Loading) (0) | 2023.05.04 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422