[JPA] JPQL ๋ฌธ๋ฒ 3 - ๊ฒฝ๋ก ํํ์, ์๋ธ ์ฟผ๋ฆฌ, ์กฐ๊ฑด์
by Dongwoongkim๊ฒฝ๋ก ํํ์
๊ฒฝ๋ก ํํ์์ .์ ์ฐ์ด ์ํฐํฐ ๊ฐ์ ๊ด๊ณ๋ฅผ ํํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ํํ์์ผ๋ก ๊ฐ์ฒด ๊ทธ๋ํ๋ฅผ ํ์ํ๋ ์์ ์ ์ฌ์ฉ๋ฉ๋๋ค.
- ์ํ ํ๋ : ๋จ์ํ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ ํ๋(ํ๋กํผํฐ)
- ์ฐ๊ด ํ๋ : ์ฐ๊ด๊ด๊ณ๋ฅผ ์ํ ํ๋์ ์๋ฒ ๋๋ ํ์
- ๋จ์ผ ๊ฐ ์ฐ๊ด ํ๋ : @ManyToOne , @OneToOne ๋จ์ผ ์ํฐํฐ ๋์
- ์ปฌ๋ ์ ๊ฐ ์ฐ๊ด ํ๋ : @OneToMany , @ManyToMany ์ปฌ๋ ์ ์ํฐํฐ ๋์
- ์๋ฒ ๋๋ ํ์
@Entity
public class Orders {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ORDER_ID")
private Long id; // ์ํ ํ๋
private int orderAmount; // ์ํ ํ๋
@Embedded
private Address address; // ์ฐ๊ดํ๋ ( ์๋ฒ ๋๋ ํ์
)
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member; // ์ฐ๊ดํ๋ ( ๋จ์ผ ์ํฐํฐ )
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product; // ์ฐ๊ดํ๋ ( ๋จ์ผ ์ํฐํฐ )
}
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MEMBER_ID")
private Long id; // ์ํ ํ๋
private String name; // ์ํ ํ๋
private int age; // ์ํ ํ๋
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team; // ์ฐ๊ด ํ๋ ( ๋จ์ผ ์ํฐํฐ )
}
@Entity
public class Team {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "TEAM_ID")
private Long id; // ์ํ ํ๋
private String name; // ์ํ ํ๋
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>(); // ์ฐ๊ด ํ๋ ( ์ํฐํฐ ์ปฌ๋ ์
)
}
- ์ํ ํ๋ ์กฐํ ์ ์ํ ํ๋๊ฐ ๊ฒฝ๋ก ํ์์ ๋์ผ๋ก ๋ ์ด์ .์ผ๋ก ํ์ํ ์ ์์ต๋๋ค. ( m.username, m.age ๊น์ง๋ง ๊ฐ๋ฅ )
- ๋จ์ผ ๊ฐ ์ฐ๊ดํ๋ ์กฐํ ์ ๋ฌต์์ ์ผ๋ก ๋ด๋ถ ์กฐ์ธ์ด ๋ฐ์ํฉ๋๋ค. ๋จ์ผ ๊ฐ ์ฐ๊ด ๊ฒฝ๋ก๋ ๊ณ์ ํ์์ด ๊ฐ๋ฅํฉ๋๋ค. ( o.product.name )
- ์ปฌ๋ ์
๊ฐ ์ฐ๊ดํ๋ ์กฐํ ์์๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ฌต์์ ๋ด๋ถ ์กฐ์ธ์ด ๋ฐ์ํฉ๋๋ค. ํ์ง๋ง ๋จ์ผ ๊ฐ๊ณผ ๋ฌ๋ฆฌ ์ปฌ๋ ์
๊ฐ ์ฐ๊ดํ๋ ์กฐํ์ ๊ฒฝ์ฐ ๊ณ์์ ์ธ ํ์์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค. ( t.members.name X )
- JPQL์ ๋ค๋ฃจ๋ฉด์ ๋ง์ด ํ๋ ์ค์๋ ์ปฌ๋ ์ ๊ฐ์์ ๊ฒฝ๋ก ํ์์ ์๋ํ๋ ๊ฒ
- FROM ์ ์์ ์กฐ์ธ์ ํตํด ๋ณ์นญ์ ์ป์ผ๋ฉด ๋ณ์นญ์ผ๋ก ํ์ํด์ผ ํฉ๋๋ค.
// ์ปฌ๋ ์
์ ๊ณ์์ ํ์์ ๋ถ๊ฐ๋ฅ
SELECT t.members.name
FROM Team t
// ์กฐ์ธ์ ํตํด ๋ณ์นญ์ ์ป์ผ๋ฉด ํ์ํด์ผ ํจ
SELECT m.name
FROM Team t INNER JOIN t.members m
๋ฌต์์ ์กฐ์ธ ์์
// JPQL
SELECT m.team ( ์ฐ๊ด๊ด๊ณ ๋จ์ผ ์ํฐํฐ ์กฐํ : ๋ฌต์์ ๋ด๋ถ ์กฐ์ธ ๋ฐ์ )
FROM Member m
// ์คํ๋๋ SQL
SELECT t
FROM Team t INNER JOIN Member m ON m.team_id = t.id
์๋ธ ์ฟผ๋ฆฌ
SQL๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก JPQL๋ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ง์ํฉ๋๋ค. ๋จ JPQL์์๋ select , from ์ ์๋ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์๋ SQL๊ณผ ๋ฌ๋ฆฌ where, having ์ ์๋ง ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
JPQL ์๋ธ ์ฟผ๋ฆฌ ํจ์
- 1. [NOT] EXISTS (subquery) : ์๋ธ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ ์ฐธ ๋ฆฌํด, NOT EXISTS์ ๋ฐ๋
- select m from Member m where exists (select t from m.team t where t.name = 'ํA' )
- -> ํ ์ด๋ฆ์ด 'ํA'๊ฐ ์์์ธ ํ์ ์กฐํ
- select m from Member m where not exists (select t from m.team t whrer t.name='ํA')
- -> ํ ์ด๋ฆ์ด 'ํA'๊ฐ ์๋ ์์์ ํ์ ์กฐํ
- 2. [ALL | ANY | SOME] (<,=,>,>=,<=) (subquery)
- ALL ์กฐ๊ฑด์ (subquery) : ์๋ธ์ฟผ๋ฆฌ๊ฐ ์กฐ๊ฑด์ ๋ชจ๋ ๋ง์กฑํ๋ฉด ์ฐธ
- select o from Order o where o.orderAmount > ALL (select p.stockAmount from Product p)
- -> ๋ชจ๋ ์ํ์ ์ฌ๊ณ ๋๋ณด๋ค ์ฃผ๋ฌธ๋์ด ๋ง์ ์ฃผ๋ฌธ๋ค ์กฐํ
- 3. ANY,SOME ์กฐ๊ฑด์ (subquery) : ์๋ธ์ฟผ๋ฆฌ๊ฐ ์กฐ๊ฑด์ ํ๋๋ผ๋ ๋ง์กฑํ๋ฉด ์ฐธ
- -> select m from Member m where m.team = ANY (select t from Team t)
- -> ์ด๋ ํ์ด๋ ํ์ ์์๋ ํ์ ์กฐํ
- 4. [NOT] IN (subquery)
- ์๋ธ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ ์ค ํ๋๋ผ๋ ๊ฐ์ ๊ฒ์ด ์์ผ๋ฉด ์ฐธ.
- select t from Team t where t IN (select t2 from Team t2 JOIN t2.members m2 where m2.age >= 20 )
- 20์ธ ์ด์์ ๋ณด์ ํ ํ
์กฐ๊ฑด์
ํ์ ํํ
- ๋ฌธ์๋ ์์ ๋ฐ์ดํ๋ก ๊ฐ์ธ์ ํํํฉ๋๋ค.
- ์ซ์๋ ํ์ ๋ณ Long์ ๊ฒฝ์ฐ L, Double์ ๊ฒฝ์ฐ D, Float์ ๊ฒฝ์ฐ F๋ฅผ ๋ถ์ฌ ํํํฉ๋๋ค. ex ) 1L,2D,3F
- ๋ ์ง๋ DATE์ ๊ฒฝ์ฐ {d '2023-05-10'}, TIME์ ๊ฒฝ์ฐ {t '18-17-05'} : 18์ 17๋ถ 5์ด, DATETIME์ ๊ฒฝ์ฐ {ts '2023-05-10 18-17-05.123'}์ผ๋ก ํํ
- Boolean์ TRUE, FALSE๋ก ํํ
์ฐ์ฐ์ ์ฐ์ ์์
1. ๊ฒฝ๋ก ํ์ ์ฐ์ฐ (.)
2. ์ํ ์ฐ์ฐ : +,-,*,/ ๋ฑ
3. ๋น๊ต ์ฐ์ฐ
4. ๋ ผ๋ฆฌ ์ฐ์ฐ
๋ ผ๋ฆฌ์ฐ์ฐ๊ณผ ๋น๊ต์
- ๋น๊ต์ :>,<, <=, >=, =, <>( ๋ ๊ฐ์ด ์๋ก ๋ค๋ฅธ์ง ํ๋จ, != ์ JPQL ๋ฐฉ์ ํํ )
- ๋ ผ๋ฆฌ ์ฐ์ฐ : AND, OR, NOT
Between, IN, LIKE ์
- Between ์: X BETWEEN A AND B โก๏ธ X ๊ฐ์ด A์ B ์ฌ์ด์ ์๋ ๊ฒฝ์ฐ ์ฐธ
- IN ์ : X IN (์์ ) โก๏ธ X์ ๊ฐ์ ๊ฐ์ด ์์ ์ ํ๋๋ผ๋ ์๋ ๊ฒฝ์ฐ ์ฐธ
- LIKE ์ : X LIKE [ํจํด ๊ฐ] โก๏ธ X๊ฐ ํจํด๊ฐ๊ณผ ์ผ์นํ๋ฉด ์ฐธ
- ํจํด ๊ฐ ์์
- '%ํ์%' : 'ํ์'์ ํฌํจํ ๋ฌธ์์ด (ํ์์ผ๋ก ์์, ๋๋๋ ๊ฒ๋ ํฌํจํฉ๋๋ค. ex) ๊นํ์, ๊นํ์๊น, ํ์, ํ์1)
- '%ํ์' : 'ํ์'์ผ๋ก ๋๋๋ ๋ฌธ์์ด (ex) ๊นํ์, Aํ์)
- 'ํ์%' : 'ํ์'์ผ๋ก ์์ํ๋ ๋ฌธ์์ด (ex) ํ์1, ํ์AA)
- '_ํ์' : 'ํ์'์ผ๋ก ๋๋๋, ์ธ๋๋ผ์ธ ๊ฐ์๋งํผ๋ง ์์ ๋ฌธ์์ด๋ก ์ฑ์์ง ๋ฌธ์์ด (ex) _ํ์ : Aํ์, 1ํ์ )
- 'ํ์_' : 'ํ์'์ผ๋ก ์์ํ๋, ์ธ๋๋ผ์ธ ๊ฐ์๋งํผ๋ง ๋ค์ ๋ฌธ์์ด๋ก ์ฑ์์ง ๋ฌธ์์ด (ex) ํ์_ : ํ์1, ํ์A )
- '_ํ์_' : 'ํ์'์ ํฌํจํ ๋ฌธ์์ด์ด๋, ์ธ๋๋ผ์ธ ๊ฐ์๋งํผ๋ง ๋ฌธ์์ด๋ก ์ฑ์์ง ๋ฌธ์์ด (ex) _ํ์__ : 1ํ์22, Aํ์BB)
- ํจํด ๊ฐ ์์
์ปฌ๋ ์ ์
์ปฌ๋ ์ ์์ ์ปฌ๋ ์ ์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
(์ปฌ๋ ์ ๊ฐ ์ฐ๊ด๊ฒฝ๋ก) IS [NOT] EMPTY
- ์ปฌ๋ ์ ์ด ๋น์ด์๋ ๊ฒฝ์ฐ ์ฐธ , NOT์ ๋น์ด์์ง ์์ ๊ฒฝ์ฐ ์ฐธ
- SELECT m FROM Member m WHERE m.orders is not empty
- -> ์ฃผ๋ฌธ์ด ํ๋๋ผ๋ ์๋ ํ์ ์กฐํ
(์ํฐํฐ or ๊ฐ) [NOT] member of (์ปฌ๋ ์ ๊ฐ ์ฐ๊ด๊ฒฝ๋ก)
- ์ํฐํฐ๋ ๊ฐ์ด ์ปฌ๋ ์ ์ ํฌํจ๋์ด ์์ผ๋ฉด ์ฐธ
- SELECT t FROM Team t where :memberParam member of t.members
- -> memberParam์ด t.members์ ๋ฉค๋ฒ ์ค ํ๋์ธ ๋ชจ๋ ํ์ ์ ํ
์ค์นผ๋ผ ์
์ค์นผ๋ผ๋ ์ซ์, ๋ฌธ์, ๋ ์ง, case, ์ํฐํฐ ํ์ ๊ฐ์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํ์ ๋ค์ ๋๋ค.
์ค์นผ๋ผ ํ์ ์ ์ฌ์ฉํ๋ ์์ ์์๋ด ์๋ค.
๋ฌธ์ํจ์
1. concat(๋ฌธ์1,๋ฌธ์2) : ๋ฌธ์๋ฅผ ๊ฒฐํฉ
2. substring(๋ฌธ์์ด, ์์น, ๊ธธ์ด) : ์์น๋ถํฐ ์์ํด ๊ธธ์ด๋งํผ substring ๊ตฌํ๊ธฐ
3. upper(๋ฌธ์),lower(๋ฌธ์) : ๋ฌธ์๋ฅผ ๋๋ฌธ์, ์๋ฌธ์๋ก ๋ณ๊ฒฝ
4. length(๋ฌธ์) : ๋ฌธ์์ด ๊ธธ์ด ๋ฆฌํด
5. locate(์ฐพ์๋ฌธ์, ์๋ณธ ๋ฌธ์, ๊ฒ์์์์์น) : ๊ฒ์์์์์น๋ถํฐ ์์ํด์ ์ฐพ์๋ฌธ์์ ์์ ์ธ๋ฑ์ค ๋ฆฌํด, ๋ชป ์ฐพ์ผ๋ฉด 0 ๋ฆฌํด
์ํํจ์
1. abs(์) : ์ ๋๊ฐ ๋ฆฌํด
2. sqrt(์) : ์ ๊ณฑ๊ทผ ๋ฆฌํด
3. mod(์ํ์, ๋๋ ์ ) : ๋๋จธ์ง ๋ฆฌํด
4. size(์ปฌ๋ ์ ๊ฐ ์ฐ๊ด ๊ฒฝ๋ก์) : ์ปฌ๋ ์ ์ ํฌ๊ธฐ ๋ฆฌํด
5. index(๋ณ์นญ) : ์ปฌ๋ ์ ํ์ ์ ์์น๊ฐ ๋ฆฌํด ex) t.members m where index(m) > 3
๋ ์งํจ์
1. CURRENT_DATE : ํ์ฌ ๋ ์ง
2. CURRENT_TIME : ํ์ฌ ์๊ฐ
3. CURRENT_TIMESTAMP : ํ์ฌ ๋ ์ง์ ์๊ฐ
์ข ๋ฃ ์ด๋ฒคํธ ์กฐํ
SELECT e
FROM Event e
WHERE e.endDate < CURRENT_DATE
CASE ์
ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ถ๊ธฐํ ๋ CASE ์ ์ฌ์ฉ.
1. ๊ธฐ๋ณธ CASE
๋ฌธ๋ฒ
CASE
[when <์กฐ๊ฑด์> them <์ค์นผ๋ผ์>}
...
ELSE <์ค์นผ๋ผ์>
END
์ฌ์ฉ ์์
SELECT
CASE WHEN m.age <= 10 then 'ํ์์๊ธ'
WHEN m.age >=60 then '๊ฒฝ๋ก์๊ธ'
else '์ผ๋ฐ์๊ธ'
END
FROM Member m
2. ์ฌํ CASE
์๋ฐ์ switch caase๋ฌธ๊ณผ ๋น์ทํฉ๋๋ค. ์กฐ๊ฑด ๋์์ ์ฌ์ฉํ ๊ฒฝ์ฐ
CASE <์กฐ๊ฑด๋์>
[when <์ค์นผ๋ผ์1> then <์ค์นผ๋ผ์2>}
ELSE <์ค์นผ๋ผ์>
END
์ฌ์ฉ ์์
SELECT
CASE t.name
WHEN 'ํA' then '์ธ์ผํฐ๋ธ100%'
WHEN 'ํB' then '์ธ์ผํฐ๋ธ120%'
else '์ธ์ผํฐ๋ธ105%'
END
FROM Team t
3. COALESCE
์ค์นผ๋ผ์์ ์ฐจ๋ก๋๋ก ์กฐํํด์ null์ด ์๋๋ฉด ๋ฆฌํด
๋ฌธ๋ฒ
COALESCE(<์ค์นผ๋ผ์>, {<์ค์นผ๋ผ์>}+)
์ฌ์ฉ์์
m.username์ด null์ด๋ฉด '์ด๋ฆ ์๋ ํ์'์ ๋ฆฌํด
SELECT coalesce(m.username,'์ด๋ฆ ์๋ ํ์')
FROM Member m
4. NULLIF
๋ฌธ๋ฒ
์ค์นผ๋ผ์ ๋ ๊ฐ๋ฅผ ๋น๊ตํด์ ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด null์ ๋ฆฌํด, ๋ค๋ฅด๋ฉด ์ฒซ ๋ฒ์งธ ๊ฐ์ ๋ฆฌํด
NULLIF (<์ค์นผ๋ผ์>, <์ค์นผ๋ผ์>)
์ฌ์ฉ์์
SELECT NULLIF(m.username,'๊ด๋ฆฌ์')
FROM Member m
m.username์ด ๊ด๋ฆฌ์์ด๋ฉด null ๋ฆฌํด, else m.username ๋ฆฌํด
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > Spring Data JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
Dongwoongkim