Spring ๊ณต๋ถ ๋ฐ ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ DB์ ๋งคํํ๋ ๊ธฐ์ ๋ก JPA๋ฅผ ๋ง์ด ์ฌ์ฉํ์๋ค.
ํนํ ๋ง์ CRUD์ JPA๋ก ์ฌ์ฉํ์๊ณ ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐฉ์ ๋๋ถ์ SQL์ ํฌ์ํ๋ ์๊ฐ์ ์๋น์ค ๋ก์ง์ ๊ฐ๋ฐํ๋ ์๊ฐ์ ๊ฐ์ง ์ ์์๋ค.
์ํฐํฐ ์ฌ๋ฌ๊ฒ๋ฅผ ๋ง๋ค๊ณ ์๋ก ํ
์ด๋ธ ๋ผ๋ฆฌ ์กฐ์ธ์ ํ ์๋ก ๋ณต์กํ๊ณ ๊ธธ์ด์ง๋ ํจ์๋ช
์ ๋ง๋ค ์ ๋ฐ์ ์๋ค.
JPA๋ก ๋ง์ฝ์ ํํฐ์ ์ ๋ชฉ ๋๋ ๊ฒ์ ์ด๋ฆ์ผ๋ก ๊ฒ์์ ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ํจ์๋ช
์ ์์ฑํด์ผ ํ๋ค.
Party findPartyByTitleOrGameTitle(String title, String gameTitle);
or
@Query("SELECT p FROM Party p WHERE p.title = :title OR p.gameTitle = :gameTitle")
Party findParty(String title, String gameTitle);
์ด๋ฐ ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ์ฒด ์งํฅ ์ฟผ๋ฆฌ ์ธ์ด์ธ JPQL์ ์ฌ์ฉํ์ฌ ์ํฐํฐ๋ฅผ ๋์์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋ค.
JPA๋ SQL์ ์ถ์ํํ ๊ฐ์ฒด ์ฟผ๋ฆฌ ์ธ์ด๋ก JPQL์ ์ ๊ณตํ๋ค.
SELECT e FROM Employee e JOIN e.department d WHERE d.name = :departmentName
public Party findPartyByTitleOrGameTitle(String title, String gameTitle) {
String jpql = "SELECT p FROM Party p WHERE p.title = :title OR p.gameTitle = :gameTitle";
TypedQuery<Party> query = entityManager.createQuery(jpql, Party.class);
query.setParameter("title", title);
query.setParameter("gameTitle", gameTitle);
List<Party> results = query.getResultList();
return results.isEmpty() ? null : results.get(0);
}
๊ทธ๋ฌ๋ ํด๋น ์ฝ๋์๋ ๋จ์ ์ด ์๋๋ฐ ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ ์๋ ๊ฒฝ์ฐ null์ ๋ฐํํ๊ณ JPQL ์ฟผ๋ฆฌ๊ฐ ๋ฉ์๋ ๋ด์ ํ๋ ์ฝ๋ฉ๋์ด ์๋ค.
์ด์ค JPQL์ ํ๋ ์ฝ๋ฉ์ ๋ฌธ์ ์ ์ ๋ํด์ ์ง์ ํ์๋ฉด
์ด์ค 3,4๋ฒ์งธ ์ด์ ๋ฅผ ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ผ๊ณ ์๊ฐ๋๋ค.
๋จผ์ ํ๋ก๊ทธ๋จ์ ๋ง๋ค๋ฉด์ ์ค๋ฅ๋ฅผ ํผํ๊ณ ์ถ์ด๋ ์๊ธธ ์ ๋ฐ์ ์๋ค. ์ค๋ฅ์๋ ์ข์ ์ค๋ฅ๊ฐ ์๊ณ ๋์ ์ค๋ฅ๊ฐ ์๋๋ฐ ๊ฐ์ฅ ์ข์ ์ค๋ฅ๋ ์ปดํ์ผ ์ค๋ฅ ์ฆ ๋น๋๋ฅผ ํ๊ธฐ์ ์ ๋ฌธ์ ์ ์ ํ์ ํ์ฌ ์คํ๋๊ธฐ ์ ์ค๋ฅ๋ฅผ ๊ฒ์ถํ๋ ๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ์ข์ ์ค๋ฅ์ด๋ค. ๋ฐํ์ ์ค๋ฅ๋ ๋ฐฐํฌ๋ฅผ ํ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์๊ธฐ์น ์์ ์ํฉ์ด ๋ฐ์ํ ์ ์๊ณ ํ๋ก๊ทธ๋จ์ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ด ๋ฎ์์ง ์ ๋ฐ์ ์๋ค.
๋๋ฒ์งธ๋ก ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฑฐ๋ ์์ ํ๋ ๊ฒ์ ๋ฌธ์์ด ์กฐ์์ ์ฝ๋๊ฐ ๋ ๋ณต์กํด์ง๊ณ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๋ค. ๋ค์ํ ์กฐ๊ฑด๋ค์ ์ฌ์ฌ์ฉํ๊ธฐ ์ด๋ ต๊ณ ๋ฌธ์์ด๋ก ์ด๋ฃจ์ด์ ธ ๋์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ด๋ ต๋ค.
http://querydsl.com/static/querydsl/5.0.0/reference/html_single/#d0e97
ํ์ํ ๋ฐฐ๊ฒฝ์ ์ดํด๋ณด๋ฉด HQL(Hibernate Query Language) ์ฟผ๋ฆฌ๋ฅผ ์ ํ ์์ ํ ๋ฐฉ์์ผ๋ก ์ ์งํด์ผ ํ ํ์์ฑ์์ ํ์ ํ์ผ๋ฉฐ ๋ฌธ์์ด์ String ์ฐ๊ฒฐ์ด ํ์ํ๊ณ ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ด๋ ต๊ฒ ๋๋ค.
์์ฝํ๋ฉด Query DSL์ ์๋ฐ ์ฝ๋๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๊ณ ํนํ ์ปดํ์ผ ์์ ์ ํ์
์ ์ฒดํฌํ์ฌ ํ์
์ ์์ ์ฑ์ ๋ณด์ฅํ๊ณ ์ฝ๋์ ๊ฐ๋
์ฑ์ ๋์ฌ์ค๋ค.
๋์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๊ณ ์์ ํ ์ ์์ด ์ ์ฐ์ฑ์ ์ ๊ณตํ๋ฉฐ ๋ณต์กํ ์ฟผ๋ฆฌ ์์
์ ์ํํ ์ ์๋ค.
๊ณต๋ถํ๋ฉด์ ์ฒ์์ ํ์์ฑ์ด ๋๋ผ์ง ๋ชป ํ๋ค. ๋์ ์ผ๋ก ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ฅผ ์กฐํํ๋ค? ๊ทธ๋ฅ JPA๋ก ์ง์ ์กฐํํ๊ฑฐ๋ ์กฐ์ธ ํ๋ฉด ๋ ๊ฒ๊ฐ์๋ฐ? ๋ผ๊ณ ์๊ฐํ์ง๋ง ์ ์ ๊ท๋ชจ๊ฐ ์ปค์ง๋ฉฐ์ ๊ฒ์์ ๋ํด์ ์ฌ๋ฌ ํํฐ๋ ๊ฒ์ ์กฐ๊ฑด๋ค์ด ๋ง์์ ธ์ ๊ฐ๋ฐ์ ์๋๊ฐ ๋๋ ค์ง๊ฒ ๋์๊ณ ์ด๋ค ์กฐ๊ฑด๋ค์ ์ฌ์ฉํ๋ฉด ์ข์๊น ๊ณ ๋ฏผํ๋ค๊ฐ ๋ค์๊ณผ ๊ฐ์ ์ฌ์ดํธ์์ ์๊ฐ์ ์ป์ด ํ๋ก์ ํธ์ ์ ์ฉํ๊ธฐ๋ก ํ์๋ค.
query string์ ๋ธ๋๋์ ๋ฌด์ ์ฌ ์คํ ๋ค๋ ๊ธ์ก์ 30000~50000์ ์ฌ์ด๋ก ๊ฒ์์ ํ์๋ ๋ค์๊ณผ ๊ฐ์ url์ ๋ณด์ฌ์ค๋ค.
์ถ์ฒ ๋ฌด์ ์ฌ
์ถ์ฒ ๋ค๋์
Query DSL์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ค์๊ณผ ๊ฐ์ ์์กด์ฑ์ ์ถ๊ฐํ๋ค.
# build.gradle
// querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
Query DSL์ ์ค์ ์ ์ถ๊ฐํ๋ค. ์ฌ๊ธฐ์์ Qclass ํ์ผ์ด ์์ฑ๋๋๋ฐ ํด๋น ํ์ผ์ ์์ฑ ์์น ๋ฐ ์์ ๋ฑ์ ์ค์ ํ๋ค.
QClass๋ Querydsl์์ ์์ฑ๋๋ ํด๋์ค๋ก, JPA ์ํฐํฐ ํด๋์ค์ ๋ํ ์ฟผ๋ฆฌ ํ์
์ ๋ํ๋ธ๋ค.
์ด ํด๋์ค๋ค์ ์ปดํ์ผ ์์ ์ Querydsl ์ด๋
ธํ
์ด์
ํ๋ก์ธ์๋ฅผ ํตํด ์์ฑ๋๋ค.
์ํฐํฐ ํด๋์ค์ ๋ํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์์ด์, ์ปดํ์ผ๋ฌ๊ฐ ํ์
์์ ํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ฉฐ ๋ฌธ์์ด ๋์ ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ
์ปดํ์ผ ์์ ์ ์ค๋ฅ๋ฅผ ๋ฐ๊ฒฌํ ์ ์๋ค.
# build.gradle
// querydsl ์ค์
def generated = 'src/main/generated' // Querydsl์ด ์์ฑํ QClass ํ์ผ์ ์ ์ฅํ ์์น๋ฅผ ์ค์
// querydsl QClass ํ์ผ ์์ฑ ์์น๋ฅผ ์ง์
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(generated))
}
// java source set ์ querydsl QClass ์์น ์ถ๊ฐ Qclass ํ์ผ์ด ์ปดํ์ด๋ ์๋ฐ ์ฝ๋์ ํจ๊ป ๋น๋๋๋๋ก ์ค์
sourceSets {
main.java.srcDirs += [generated]
}
// gradle clean ์์ QClass ๋๋ ํ ๋ฆฌ ์ญ์
clean {
delete file(generated)
}
// Querydsl์ด ์์ฑํ QClass ํ์ผ์ด JAR ํ์ผ์ ํฌํจ๋์ง ์๋๋ก ์ค์
jar {
enabled = false
}
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@SQLDelete(sql = "UPDATE partys SET deleted_at=CURRENT_TIMESTAMP where id=?")
@Where(clause = "deleted_at IS NULL")
@Table(name = "partys")
public class Party extends Timestamped {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String contents;
@Column(nullable = false)
private Boolean status;
@Column(nullable = false)
private int view;
@Column(nullable = false)
private LocalDateTime deadline;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "game_id")
private Game game;
}
Gradle ์ฐฝ์ ๋ณด๋ฉด build ํด๋์ build๋ผ๋ ์์ด์ฝ์ ํด๋ฆญ์ํ๋ค.
๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด gradle ํ์ผ์ query dsl์ ์ค์ ๋ 'src/main/generated'์ QClass ํ์ผ์ด ์์ฑ๋๋ค.
QeuryDSL์ ์ฌ์ฉํ๊ธฐ์ํด 4๊ฐ์ง ํ์ผ์ ์ฌ์ฉํ์๋ค.
BooleanExpression์ผ๋ก SearchCondition์ ๊ฒ์ ์กฐ๊ฑด ํจ์๋ฅผ ๋ง๋ ๋ค. null์ ๋ฐํํ๋ฉด where
์ ์์ ํด๋น ์กฐ๊ฑด์ ๋ฌด์ํ ์ ์๋ค.
๋๋ ์์ฑ์๋ฅผ ์ด์ฉํด์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ ํ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค. ์ํฐํฐ ์์ฒด๋ฅผ ๋ฐํํ ์ง ์๋๋ฉด domain์ผ๋ก ๋ฐํํ ์ง๋ ํ๋ก์ ํธ ์งํํ๋ฉด์ ๊ณ์ํด์ ๊ณ ๋ฏผํด์ผํ ์ฌํญ์ด๋ค.
Querydsl๋ ํ์ด์ง ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ฐ Pageable
์ ์ธ์๋ก ๋ฐ๋ ํํ๋ก ๊ฐ๋ฅํ๋ค.
offset
์ ํตํด Pageable์ ํ์ด์ง ๋ฒํธ๋ฅผ ์ค์ ํ๊ณ limit
์ ํ์ด์ง ์ฌ์ด์ฆ๋ฅผ ์ค์ ํ๋ค.
์ ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๋ณดํต orderby
์ ์ฝ์
ํ๋ฉด ๋์ง๋ง ์ด๊ฒ ์ญ์ ๋์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด์ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค
์ผ๋ฐ ์กฐ๊ฑด ๋ช
์ด ์๋ OrderSpecifier
ํ์ด ํ์ํ๋ค.
QueryDSL์์ ์ ๋ ฌ ์กฐ๊ฑด์ ๋ํ๋ด๋ ํด๋์ค์ด๋ฉฐ ORDER BY
์ ์ ์ฌํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
Pageable
๊ฐ์ฒด์์ ์ ๋ ฌ ์กฐ๊ฑด์ ๊ฐ์ ธ์จ๋ค.created
(์์ฑ์ผ), view
(์กฐํ์)๋ผ๋ ์ ๋ ฌ ์กฐ๊ฑด์ด ์กด์ฌํ๋ฉด ํด๋น ์กฐ๊ฑด์ ๋ฆฌ์คํธ์ ์ฝ์
ํ๋ค.(์ ๋ ฌ ์กฐ๊ฑด ์ถ๊ฐ ๊ฐ๋ฅ)ํํฐ์์ ๊ฒ์์ด ๋ฆฌ๊ทธ์ค๋ธ๋ ์ ๋
์ด๋ฉด์ ์ ๋ชฉ์ด ๋ญํฌ
๋ผ๋ ๊ธ์๊ฐ ๋ค์ด๊ฐ๊ณ ์กฐํ์๊ฐ ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ ๊ฒฐ๊ณผ(์ ๋ ฌ์ ์ฝค๋ง๋ฅผ ๋ฃ์ด์ผํ๋ค. ,asc ,desc)
QClass๋ฅผ importํ ๋ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ๋ค. ์ด๋ build๋ฅผ Intellij์์ gradle๋ก ๋ณ๊ฒฝํ๋ค.
์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆด๋ ๋ง์ฝ ์ ๋ ฌ ์์ ๋ฐํ๊ฐ์ null
๋ก ์ฃผ์์๋
QueryDSL์ OrderBy๋ null์ ์ง์ํ์ง ์์ NullExpression.DEFAULT๋ฅผ ์ฌ์ฉ ๋ฐ ๊ถ์ฅํ๋ค.
ํํฐ์ ๊ฒ์, ์์ฑ์๋ฅผ ์กฐ์ธ ์ฟผ๋ฆฌ๋ฅผ ์ด์ฉํด์ ๋ ๋ฆด๋ ๋ค์๊ณผ ๊ฐ์ด ์ฟผ๋ฆฌ๋ฅผ 3๊ฐ๋ฅผ ๋ฐ๋ก ๋ ๋ฆฌ๋ฉด์ ์ํํ๋ค.
fetch join์ ์ด์ฉํด์ ์ฟผ๋ฆฌ๋ฅผ ํ๋ฒ์ ๋ณด๋ด ์ฟผ๋ฆฌ ๊ฐฏ์๋ฅผ ์ค์๋ค.
์ฐธ๊ณ ์๋ฃ
์ธํ๋ฐ ์ค์ Querydsl
https://thalals.tistory.com/400