코딩하는 오징어
JPQL 빌더 클래스 QueryDsl 사용법 본문
반응형
QueryDsl이란?
- JPQL의 빌더(Criteria)클래스
QueryDsl 사용전 설정
- dependency 추가
dependencies { compile("com.querydsl:querydsl-core:4.2.1") compile("com.querydsl:querydsl-apt:4.2.1") compile("com.querydsl:querydsl-jpa:4.2.1") compile("com.querydsl:querydsl-collections:4.2.1") ... }
- Q클래스를 먼저 생성 후 컴파일 되어야 하므로 task를 먼저 실행시켜야함
def queryDslOutput = file("src-gen/main/java") sourceSets { main { java { srcDir "src-gen/main/java" } } } clean { delete queryDslOutput } task generateQueryDSL(type: JavaCompile, group: "build") { doFirst { if (!queryDslOutput.exists()) { logger.info("Creating `$queryDslOutput` directory") if (!queryDslOutput.mkdirs()) { throw new InvalidUserDataException("Unable to create `$queryDslOutput` directory") } } } source = sourceSets.main.java classpath = configurations.compile options.compilerArgs = [ "-proc:only", "-processor", "com.querydsl.apt.jpa.JPAAnnotationProcessor" ] destinationDir = queryDslOutput options.failOnError = false } compileJava { dependsOn generateQueryDSL //이 부분 dependsOn이 generateQueryDSL이다. source generateQueryDSL.destinationDir }
QueryDsl 사용법
example entity(다음 두 entity는 1:N관계)
- User
- Account
User.java
@Entity @Table(name = "tb_user") @Getter @Setter @EqualsAndHashCode public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonIgnore private Long id; @Column(name = "name", nullable = false) private String name; @Column(name = "age", nullable = false) private Long age; }
- Account.java
@Entity @Table(name = "tb_account") @Getter @Setter public class Account { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonIgnore private Long id; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "user_id", referencedColumnName = "id") @JsonIgnore private User userId; @Column(name = "account") private String account_num; @Column(name = "money") private Double money; @Column(name = "bank_name") private String bankName; @PrePersist public void initMoney() { this.money = 0D; } }
- UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long>, CustomUserRepository {
Optional<User> findByName(String name);
}
- CustomUserRepository.java
public interface CustomUserRepository { List<User> findAllUserByAgeLimit(Integer limitCount); List<String> findAllNameByAgeLimit(Integer limitCount); List<AccountUserJoinDto> findAllUserGreaterThanAge(Long age); }
- UserRepositoryImpl.java
@NoRepositoryBean public class UserRepositoryImpl extends QuerydslRepositorySupport implements CustomUserRepository { //QuerydslRepositorySupport 클래스에는 기본생성자가 없음. public UserRepositoryImpl() { super(User.class); } @Override public List<User> findAllUserByAgeLimit(Integer limitCount) { QUser user = QUser.user; return from(user) .where(user.age.eq(25L)) .limit(limitCount) .fetch(); } @Override public List<String> findAllNameByAgeLimit(Integer limitCount) { QUser user = QUser.user; return from(user) .where(user.age.eq(25L)) .limit(limitCount) .select(user.name) .fetch(); } @Override public List<AccountUserJoinDto> findAllUserGreaterThanAge(Long age) { QUser user = QUser.user; QAccount account = QAccount.account; JPQLQuery<AccountUserJoinDto> query = from(account) .innerJoin(account.userId, user) .select(Projections.constructor(AccountUserJoinDto.class, user.name, user.age, account.money, account.bankName)) .where(user.age.gt(age)); return query.fetch(); } }
findAllUserGreaterThanAge 함수 호출시 다음과 같은 쿼리가 생성되어 DB에 전달됨.
다음 innerJoin함수를 보면 감이 오겠지만 account 변수의 위치에 주의하자.
from(account).innerJoin(account.userId, user)...
select user1_.name as col_0_0_, user1_.age as col_1_0_, account0_.money as col_2_0_, account0_.bank_name as col_3_0_ from tb_account account0_ inner join tb_user user1_ on account0_.user_id=user1_.id where user1_.age>?
반응형
'Framework > JPA' 카테고리의 다른 글
Persistence Context와 Transaction Isolation (1) | 2020.12.12 |
---|---|
Kotlin + JPA 사용시 Entity 정의 (8) | 2020.11.28 |
Kotlin으로 개발 할 때 주의할 점(1) (0) | 2019.02.04 |
JPA 영속성 컨텍스트와 Entity 관계설정 기본 (0) | 2018.12.09 |
Optimistic Lock과 Pessimistic Lock (1) | 2018.12.09 |
Comments