์๋ฐ ORM ํ์ค JPA ํ๋ก๊ทธ๋๋ฐ - ๊ธฐ๋ณธํธ์ ๊ณต๋ถํ๋ฉฐ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.
๋ชฉ์ฐจ
- JPQL ์๊ฐ
- ํ๋ก์ ์ (SELECT)
- ํ์ด์ง
- ์กฐ์ธ
- ์๋ธ์ฟผ๋ฆฌ
- JPQL ํ์ ํํ๊ณผ ๊ธฐํ์
- ์กฐ๊ฑด์(CASE ๋ฑ๋ฑ)
- JPQL ํจ์
๐ JPQL ์๊ฐ
- JPQL์ ๊ฐ์ฒด์งํฅ ์ฟผ๋ฆฌ ์ธ์ด์ด๋ค. ๋ฐ๋ผ์ ํ ์ด๋ธ์ ๋์์ผ๋ก ์ฟผ๋ฆฌํ๋ ๊ฒ์ด ์๋๋ผ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌํ๋ค.
- JPQL์ SQL์ ์ถ์ํํด์ ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค SQL์ ์์กดํ์ง ์๋๋ค.
- JPQL์ ๊ฒฐ๊ตญ SQL๋ก ๋ณํ๋๋ค.
JPQL ๋ฌธ๋ฒ
- select m from Member as m where m.age > 18
- ์ํฐํฐ์ ์์ฑ์ ๋์๋ฌธ์ ๊ตฌ๋ถo (Member, age)
- JPQL ํค์๋๋ ๋์๋ฌธ์ ๊ตฌ๋ถx (SELECT, FROM, where)
- ์ํฐํฐ ์ด๋ฆ ์ฌ์ฉ, ํ ์ด๋ธ ์ด๋ฆ ์๋!
- ๋ณ์นญ์ ํ์(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 : ๋ฐํ ํ์ ์ด ๋ช ํํ ๋ ์ฌ์ฉ
/* ํ์
์ด ๋ช
ํํ ๋ */
TypedQuery<Member> query = em.createQuery("select m from Member m", Member.class);
- Query : ๋ฐํ ํ์ ์ด ๋ช ํํ์ง ์์ ๋ ์ฌ์ฉ
/* ๋ช
ํํ์ง ์์ ๋ */
Query query = em.createQuery("select m.username, m.age from Member m");
String(username), int(age) ๋๊ฐ์ ํ์ ์ด ์์ฌ ์์ด์ ํ์ ์ ๋ณด๋ฅผ ๋ฐ์ ์ฌ ์ ์์.
๊ฒฐ๊ณผ ์กฐํ API
- query.getResultList()
- ๊ฒฐ๊ณผ๊ฐ ํ๋ ์ด์์ผ ๋, ๋ฆฌ์คํธ ๋ฐํ (๊ฒฐ๊ณผ๊ฐ ์์ ๋ ๋น์ด์๋ ๋ฆฌ์คํธ ๋ฐํ)
- query.getSingleResult()
- ๊ฒฐ๊ณผ๊ฐ ์ ํํ ํ๋, ๋จ์ผ ๊ฐ์ฒด ๋ฐํ
- ๋ ๋ค exception ํฐ์ง๋๊น ์ ๋ง์ ๋ง์ ๋ง ์กฐ์ฌํด์ ์ฌ์ฉ!
- ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด: javax.persistence.NoResultException
- ๋ ์ด์์ด๋ฉด: javax.persistence.NonUniqueResultException
ํ๋ผ๋ฏธํฐ ๋ฐ์ธ๋ฉ - ์ด๋ฆ ๊ธฐ์ค, ์์น ๊ธฐ์ค
์ด๋ฆ ๊ธฐ์ค
select m from Member m where m.username=:username
query.setParameter("username", usernameParam); // username == usernameParam์ธ ๋ฐ์ดํฐ ์กฐํ
์์น ๊ธฐ์ค
(๋ง์ฝ ์ค๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ค๊ณ ๊ฐ์ ํ์ ๋, ์ธ๋ฑ์ค๊ฐ 1์ฉ ๋ฐ๋ฆฌ๊ธฐ ๋๋ฌธ์, ์ ๋งํด์๋ ์ฌ์ฉํ์ง ์๋๊ฒ์ด ์ข๋ค.)
select m from Member m where m.username=?1
query.setParameter(1, usernameParam);
๋ฉ์๋ ์ฒด์ธ ๋ฐฉ์์ฒ๋ผ ์ฌ์ฉ
TypeQuery<Member> query = em.createQuery("select m from Member m where m.username=:username", Member.class);
query.setParameter("username", "member1");
Member singleResult = query.getSingleResult();
/* ๋ฉ์๋ ์ฒด์ธ ๋ฐฉ์ ์ฌ์ฉ */
Member result = em.createQuery("select m from Member m where m.username=:username", Member.class)
.setParameter("username", "member1")
.getSingleResult();
๐ ํ๋ก์ ์
- ์ ์ : 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๋ก ์ค๋ณต ์ ๊ฑฐ */
SELECT๋ก ์กฐํํ ๋ชจ๋ member๋ค์ ์ ๋ถ ๋ค ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ ๋๋ค.
List<Team> resultList = em.createQuery("select t from Member m join m.team t", Team.class)
.getResultList();
join์ ๋ช ์์ ์ผ๋ก ํํ ํด์ฃผ๋ ๊ฒ์ด ์ข๋ค!
ํ๋ก์ ์ - ์ฌ๋ฌ ๊ฐ ์กฐํ
SQL
- SELECT m.username, m.age FROM Member m
List resultList = em.createQuery("select m.age, m.username from Member m")
.getResultList();
Query ํ์ ์ผ๋ก ์กฐํ
Object๊ฐ์ฒด๋ฅผ Object[] ํ์ ์บ์คํ ํด์ ์ฌ์ฉํ๊ธฐ.
Object o = resultList.get(0);
Object[] result = (Object[]) o; // object๋ฐฐ์ด์ [m.age, m.username] ์ด๋ฐ ์์ผ๋ก ๋ค์ด์๋ค.
System.out.println("age = " + result[0]); // age
System.out.println("username = " + result[1]); // username
Object[] ํ์ ์ผ๋ก ์กฐํ
์ ๋ค๋ฆญ์ Object[] ํ์ ์ ์ธ.
List<Object[]> resultList = em.createQuery("select m.age, m.username from Member m")
.getResultList();
Object[] result1 = resultList.get(0);
System.out.println("age = " + result1[0]); // age
System.out.println("username = " + result1[1]); // username
new ๋ช ๋ น์ด๋ก ์กฐํ
๊ฐ๋จํ DTO ์์ฑํด์ DTOํ์ ์ผ๋ก ๋ฝ๋ ๋ฐฉ๋ฒ
List<MemberDTO> resultList = em.createQuery(
"select new package๋ช
.MemberDTO(m.age, m.username) from Member m", MemberDTO.class)
.getResultList(); // ๋ง์น MemberDTO์ ์์ฑ์๋ฅผ ํธ์ถํ๋ ๊ฒ ์ฒ๋ผ!
MemberDTO memberDTO = resultList.get(0);
System.out.println("memberDTO.age = " + memberDTO.getAge()); // age
System.out.println("memberDTO.username = " + memberDTO.getUsername()); // username
SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m
- ํจํค์ง ๋ช ์ ํฌํจํ ์ ์ฒด ํด๋์ค ๋ช ์ ๋ ฅ
- ์์์ ํ์ ์ด ์ผ์นํ๋ ์์ฑ์ ํ์!
๐ ํ์ด์ง API
- JPA๋ ํ์ด์ง์ ๋ค์ ๋ API๋ก ์ถ์ํ
- setFirstResult(int startPosition) : ์กฐํ ์์ ์์น(0๋ถํฐ ์์)
- setMaxResults(int maxResult) : ์กฐํํ ๋ฐ์ดํฐ ์
// Member 100๊ฐ ๋ฏธ๋ฆฌ persist
List<Member> resultList = em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(0) // ํ์ด์ง : ์กฐํ ์์ ์์น(0๋ถํฐ ์์)
.setMaxResults(10) // ํ์ด์ง : ์กฐํํ ๋ฐ์ดํฐ ์(10๊ฐ)
.getResultList(); // ๊ฒฐ๊ณผ๊ฐ์ List๋ก
for(Member member : resultList) {
System.out.println("member = " + member); // member.toString() ์ค๋ฒ๋ผ์ด๋ฉ ํ์
}
์คํ ์ฟผ๋ฆฌ
order by .. desc limit ? ์ธ ์ด์ ๋ setFirstResult(0)์ผ๋ก ์คฌ๊ธฐ ๋๋ฌธ์ด๋ค.
setFirstResult(1)๋ก ์ฃผ๋ฉด?
offset์ด ์ค์ ๋จ.
๐ ์กฐ์ธ(JOIN)
๋ด๋ถ์กฐ์ธ (inner join)
- inner ์๋ต ๊ฐ๋ฅ.
String qlString = "select m from Member m inner join m.team t";
List<Member> resultList = em.createQuery(qlString, Member.class);
.getResultList();
์? team์ ์กฐํํ๊ฑด ์๊ฒ ๋๋ฐ, team์ ์ฌ์ฉํ์ง ์์๋๋ฐ ์ ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ๊น?
์ด๊ฒ ๋ฐ๋ก @ManyToOne์ fetch ๊ธฐ๋ณธ ๊ฐ์ด EAGER์ด๊ธฐ ๋๋ฌธ! (LAZY๋ก ๋ฐ๊ฟ์ฃผ๋๋ก ํ์)
์ธ๋ถ ์กฐ์ธ(outer join)
- outer ์๋ต ๊ฐ๋ฅ
String qlString = "select m from Member m left outer join m.team t";
List<Member> resultList = em.createQuery(qlString, Member.class);
.getResultList();
๐ on ์
์กฐ์ธ ๋์ ํํฐ๋ง
String qlString = "select m from Member m left join m.team t on t.name = 'teamA'";
List<Member> resultList = em.createQuery(qlString, Member.class)
.getResultList();
member.id ์ team.id๋ฅผ ๋น๊ตํด์ andํด์ ์ถ๊ฐ๋ก member.username ๊ณผ team.name์ด ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ด๋ค.
+ where๋ก ์กฐํ ๊ฒฐ๊ณผ
String qlString = "select m from Member m join m.team t where t.name = 'teamA'";
List<Member> resultList = em.createQuery(qlString, Member.class)
.getResultList();
์ฐ๊ด๊ด๊ณ ์๋ ์ํฐํฐ ์ธ๋ถ ์กฐ์ธ
String qlString = "select m from Member m left join Team t on m.username = t.name";
List<Member> resultList = em.createQuery(qlString, Member.class)
.getResultList();
์ฐ๊ด๊ด๊ณ๊ฐ ์๋ ํ๋(id๊ฐ ์๋ username์ด๋ผ๋์ง ๋ฑ๋ฑ..)๋ฅผ ์กฐ์ธํ ๋, id๊ฐ์ ๊ฐ์ ธ์ค์ง ์๊ณ name๋ผ๋ฆฌ๋ง ๋น๊ตํ์ฌ ๊ฐ์ ๊ฐ์ง๊ณ ์จ๋ค.
+ where๋ก ์กฐํ ๊ฒฐ๊ณผ
String qlString = "select m from Member m join m.team t where m.username = t.name";
List<Member> resultList = em.createQuery(qlString, Member.class)
.getResultList();
Member, Team์ ์ฐ๊ด๊ด๊ณ๊ฐ ์๋๋ฐ ์ ์ฐ๊ด๊ด๊ณ๊ฐ ์๋ค๊ณ ๋งํ ๊น?
ํ์๊ณผ ํ์ด ์ฐ๊ด๊ด๊ณ๊ฐ ์๋ ๊ฑด ๋ง์ง๋ง, ํ์์ ์ด๋ฆ๊ณผ ํ ์ด๋ฆ์ ์๋ก ์๋ฌด๋ฐ ์ฐ๊ด๊ด๊ณ๊ฐ ์๋ ํ๋์ด๋ค.
์ด๋ฌํ ์ฐ๊ด๊ด๊ณ๊ฐ ์๋ ํ๋๋ก ์กฐ์ธํ๋ ๋ฐฉ๋ฒ์ ์ธํ ์กฐ์ธ์ด๋ผ๊ณ ํ๊ณ , ์๋ฅผ ๋ค์ด์ ์ธํ ์กฐ์ธ์ ์ฌ์ฉํ๋ฉด
ํ์๊ณผ ํ์ด ์๋๋ผ, ํ ์ด๋ฆ๊ณผ ํ์ ์ด๋ฆ์ด ๊ฐ์ ํ๋๋ก๋ ์กฐ์ธ์ด ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
๐ ์๋ธ ์ฟผ๋ฆฌ
์๋ธ ์ฟผ๋ฆฌ
- ์ฟผ๋ฆฌ ์์ ๋ ๋ค๋ฅธ ์ฟผ๋ฆฌ
์๋ธ ์ฟผ๋ฆฌ ์ง์ ํจ์
- EXISTS : ์๋ธ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ๊ฐ ์กด์ฌํ๋ฉด ์ฐธ
- ALL, ANY, SOME : ALL์ ๋ชจ๋ ๋ง์กฑํ๋ฉด ์ฐธ, ANY, SOME์ ์กฐ๊ฑด์ ํ๋๋ผ๋ ๋ง์กฑํ๋ฉด ์ฐธ
- IN : ์๋ธ ์ฟผ๋ฆฌ์ ๊ฒฐ๊ณผ ์ค ํ๋๋ผ๋ ๊ฐ์ ๊ฒ์ด ์์ผ๋ฉด ์ฐธ
์์ 1. ๋์ด๊ฐ ํ๊ท ๋ณด๋ค ๋ง์ ํ์
SELECT m FROM Member m WHERE m.age > (SELECT avg(m2.age) FROM Member m2)
์๋ธ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ฉด ๊ธฐ์กด์ Member m์ ์ฌ์ฉํ์ง ์๊ณ , ์๋ก์ด m2๋ฅผ ๋ง๋ค์ด์ ์กฐํ ํ๋ค. (์ด๋ ๊ฒ ํด์ผ ์ฑ๋ฅ์ด ์ ๋์ค๊ฒ ๋๋ค.)
์์ 2. ํ ๊ฑด์ด๋ผ๋ ์ฃผ๋ฌธํ ๊ณ ๊ฐ
SELECT m FROM Member m WHERE (SELECT count(o) FROM Order o WHERE m = o.member) > 0
๋ฉ์ธ ์ฟผ๋ฆฌ์์ ์กฐํํ member์ ์ผ์นํ Order.member์ ์ฃผ๋ฌธ ๊ฑด์๊ฐ 0 ๋ณด๋ค ํด ๋ ์กฐํ ํด ์จ๋ค.
์๋ธ ์ฟผ๋ฆฌ ์ฌ์ฉ
SELECT m FROM Member m WHERE exists (SELECT t FROM m.team t WHERE t.name = 'teamA')
exists ํจ์๋ ๊ฒฐ๊ณผ๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ true๋ฅผ, ์๋ ๊ฒฝ์ฐ false๋ฅผ ๋ฆฌํดํ๋ค.
์์ ์ฝ๋๋ member๊ฐ 'teamA' ์์์ธ์ง ํ์ธ ํ๋ sql์ด๋ค.
SELECT o FROM Order o WHERE o.orderAmount > ALL (SELECT p.stockAmount FROM Product p)
์ ์ฒด ์ํ ๊ฐ๊ฐ์ ์ฌ๊ณ ๋ณด๋ค ์ฃผ๋ฌธ๋์ด ๋ง์ ์ฃผ๋ฌธ๋ค์ ์กฐํํด ์ค๋ sql์ด๋ค.
SELECT m FROM Member m WHERE m.team = ANY(select t from Team t)
์ด๋ค ํ์ด๋ ํ์ ์์๋ ํ์์ ์กฐํํด ์ค๋ sql์ด๋ค.
๐ JPQL ํ์ ํํ๊ณผ ๊ธฐํ์
- ๋ฌธ์ : 'HELLO' , 'She''s' (์ค๊ฐ์ ' ๋ฃ๊ธฐ ์ํด์)
- ์ซ์ : 10L(Long), 10D(Double), 10F(Float)
- Boolean : True, False (๋์๋ฌธ์ ๊ตฌ๋ถ x)
- Enum : ํจํค์ง๋ช ํฌํจ
- ์ํฐํฐ ํ์ : Type(m) = Member (์์ ๊ด๊ณ์์ ์ฌ์ฉ)
๋ฌธ์, boolean, Enum ํ์
// enum ํ์
์ ํญ์ FQCN(Fully Qualified Class Name)์ ์ ์ด์ค์ผ ํ๋ค.
String sql = "select m.username, 'HELLO', true From Member m " +
"where m.type = ch10.MemberType.ADMIN";
List<Object[]> result = em.createQuery(sql)
.getResultList();
for (Object[] objects : result) {
System.out.println(objects[0]);
System.out.println(objects[1]);
System.out.println(objects[2]);
}
์ฟผ๋ฆฌ๋ฅผ ๋ณด๋ฉด, MemberType.ADMIN์ผ๋ก ์กฐํ ํ๊ณ ์๋ค.
DTYPE
String sql = "select i From Item i" +
"where type(i) = Book"; // DTYPE = 'BOOK' ์ผ๋ก ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ๋ค.
๐ ์กฐ๊ฑด์(CASE ๋ฑ๋ฑ)
๊ธฐ๋ณธ CASE ์ (๋์ด์ฐ๊ธฐ ์ฃผ์)
String query = "select " +
"case when m.age <= 10 then 'ํ์์๊ธ'" +
"when m.age >= 60 then '๊ฒฝ๋ก์๊ธ'" +
"else '์ผ๋ฐ์๊ธ'" +
"end " +
"from Member m";
ํํ๋ java์ switch๋ฌธ์ด๋ ๋น์ทํ๋ค.
member์ ๋์ด๊ฐ 10์ดํ์ด๋ฉด "ํ์์๊ธ", 60์ด์์ด๋ฉด "๊ฒฝ๋ก์๊ธ", ๋๋จธ์ง ๋์ด๋ "์ผ๋ฐ์๊ธ"์ผ๋ก ์ถ๋ ฅ๋๋ค.
๋จ์ CASE ์
String query = "select " +
"case m.team.name " +
"when 'teamA' then 'ํA'" +
"when 'teamB' then 'ํB'" +
"else '๊ทธ ์ธ ํ'" +
"end " +
"from Member m";
๊ธฐ๋ณธ CASE๋ฌธ๊ณผ ์ด์ง ๋ค๋ฅด๋ค. case๋ฌธ ์์ ๊ฐ์ ์ง์ ํด ๋๊ณ , ๊ทธ ๊ฐ์ด when 'A' ์ผ๋ -> then ... ๋ when 'B'์ผ๋๋ -> then ... ์ด๋ฐ ์์ผ๋ก ์์ฑํ๋ค.
COALESCE : ํ๋์ฉ ์กฐํํด์ null์ด ์๋๋ฉด ๋ฐํ
- ์ฌ์ฉ์ ์ด๋ฆ์ด null(์์ผ๋ฉด)์ด๋ฉด ์ด๋ฆ ์๋ ํ์์ ๋ฐํ
member.setUsername(null);
..
String query = "select coalesce(m.username, '์ด๋ฆ ์๋ ํ์') from Member m";
NULLIF : ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด null ๋ฐํ, ๋ค๋ฅด๋ฉด ์ฒซ๋ฒ์งธ ๊ฐ ๋ฐํ
- ์ฌ์ฉ์ ์ด๋ฆ์ด '๊ด๋ฆฌ์'์ด๋ฉด null์ ๋ฐํ, ์๋๋ฉด ์๊ธฐ ์์ ์ ์ด๋ฆ ๋ฐํ
member.setUsername("๊ด๋ฆฌ์");
..
String query = "select nullif(m.username, '๊ด๋ฆฌ์') from Member m";โ
๐ JPQL ๊ธฐ๋ณธ ํจ์, ์ฌ์ฉ์ ์ ์ ํจ์
JPQL ๊ธฐ๋ณธ ํจ์
์ฌ์ฉ์ ์ ์ ํจ์
- ํ์ด๋ฒ๋ค์ดํธ๋ ์ฌ์ฉ์ ์ ๋ฐฉ์ธ์ ์ถ๊ฐํด์ผ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
- ์ฌ์ฉํ๋ DB ๋ฐฉ์ธ์ ์์๋ฐ๊ณ , ์ฌ์ฉ์ ์ ์ ํจ์๋ฅผ ๋ฑ๋กํ๋ค.
๋ฑ๋ก ํ์ ์๋์ ๊ฐ์ด ์ฌ์ฉํ ์ ์๋ค.
select function('group_concat' , i.name) from Item i
๋คํํ๋ ์ฌ๋งํ๋ฉด, DB์ ์ด๋ฏธ ๋ค ๋ฑ๋ก์ด ๋์ด์๊ธด ํ๋ค.
- concat (๋ฌธ์์ด ๋ํ๊ธฐ)
String query = "select concat('a', 'b') from Member m";
// ์คํ ๊ฒฐ๊ณผ : ab
- SUBSTRING (๋ฌธ์์ด ์๋ฅด๊ธฐ)
String query = "select substring('abcdef', 2, 3) from Member m";
// ์คํ ๊ฒฐ๊ณผ : bcd
- TRIM (๊ณต๋ฐฑ ์ ๊ฑฐ)
- LTRIM (์์ ๋ฌธ์์ด ๊ณต๋ฐฑ ์ ๊ฑฐ)
- RTRIM (๋ ๋ฌธ์์ด ๊ณต๋ฐฑ ์ ๊ฑฐ)
String query = "select trim(' abcdef ') from Member m"; // "abcdef"
String query = "select Ltrim(' abcdef ') from Member m"; // "abcdef "
String query = "select Rtrim(' abcdef ') from Member m"; // " abcdef"
- LOCATE (ํด๋น ๋ฌธ์ ์์น)
- return Integer ํ์
String query = "select locate('cd', 'abcdef') from Member m"; // ๊ฒฐ๊ณผ ๊ฐ : 3
SIZE (ํฌ๊ธฐ)
String query = "select size(t.members) from Team t"; // team์ ์๋ ๋ฉค๋ฒ๋ฅผ ์ ์ฅํ๋ ์ปฌ๋ ์
์ ์ฌ์ด์ฆ๋ฅผ ์กฐํ
์ฌ์ฉ์ ์ ์ ํจ์ ๋ง๋ค๊ธฐ
1. ํจํค์ง ์์ฑ - MyH2Dialect ํด๋์ค ์์ฑ
์ง๊ธ์ H2๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์, H2Dialect๋ฅผ ์์ ๋ฐ์์ ์์ฑํ๋ค.
package dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StandardBasicTypes;
/**
* H2Dialect ๋ฅผ ์์๋ฐ์์ ๋ด๊ฐ ์ฌ์ฉํ๊ณ ์ถ์ ํจ์๋ฅผ ๋ฑ๋ก ์ํฌ ์ ์๋ค.
* <p>
* ์ด๋ป๊ฒ ์์ฑํ๋์ง๋ H2Dialect ํด๋์ค ๋ค์ด๊ฐ์ registerFunction ๋ฉ์๋๋ฅผ ๋ณด๊ณ ์ฐธ์กฐํ๋ฉด ๋๋ค.
*/
public class MyH2Dialect extends H2Dialect {
public MyH2Dialect() {
registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
}
}
์ ์ ํจ์๋ฅผ ๋ง๋ค๋ H2Dialect ํด๋์ค์ ๋ฑ๋ก๋ ๋ฉ์๋๋ฅผ ์ดํด๋ณด๊ณ ์ฐธ์กฐํ์.
persistence.xml ํ์ผ์ ๊ธฐ์กด์ ๋ฑ๋ก๋์ด์๋ H2Dialect๋ฅผ ํ์ฌ ์์ฑํ MyH2Dialect๋ก ๋ฐ๊ฟ์ค๋ค.
// <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.dialect" value="dialect.MyH2Dialect"/>
group_concat ์ ๋ฐ์ดํฐ๋ฅผ ํ์ค๋ก ๋ง๋ค์ด์ฃผ๋ ํจ์์ด๋ค.
String query = "select function('group_concat', m.username) from Member m";
์ฐธ๊ณ ๋ก, ํ์ด๋ฒ๋ค์ดํธ ์ฌ์ฉ์ค์ผ ๋๋ ์๋ ๋ฐฉ๋ฒ๋ ๊ฐ๋ฅํ๋ค.
String query = "select group_concat(m.username) from Member m"; // member1, member2