스프링부트 JPA [ 다양한 쿼리 생성 방법 ]
1. JPARepository에서 제공되는 메서드를 사용하는 방법
2. 메서드 이름으로 쿼리를 생성하는 방법
3. 사용자 정의 쿼리 JPQL(Java Persistence Query Language)
3-1 Entity기준으로 만드냐 or 3-2 Table기준으로 만드냐
4. 동적 쿼리 처리를 위한 Querydsl - API를 사용(쿼리문이 아니라)
[ JPARepository에서 제공되는 메서드를 사용하는 방법 ]
public interface CustomerRepository extends JpaRepository<Customer, Long> {
//1. jparepository에서 제공되는 메서드를 사용하는 방법
public List<Customer> findByAge(int age); //30
}
public class CustomerController {
@Autowired
private CustomerRepository customerRepository;
@GetMapping("/customer/{age}")
public ResponseEntity<?> getByAge(@PathVariable int age){
List<Customer> cus=customerRepository.findByAge(age);
return new ResponseEntity<>(cus, HttpStatus.OK);
}
[ 메서드 이름으로 쿼리를 생성하는 방법 ]
public interface CustomerRepository extends JpaRepository<Customer, Long> {
//2. 메서드 이름으로 쿼리 생성하는 방법
public Customer findByUsernameAndPassword(String username, String password); //username과 password가 일치하는 사람
public Customer findByUsernameIs(String username); //name같은 사람 찾는 메서드
public List<Customer> findByAgeGreaterThanEqual(int age);
}
@RestController
@RequestMapping("/api")
public class CustomerController {
@Autowired
private CustomerRepository customerRepository;
@PostMapping("/customer")
public ResponseEntity<?> getUsernameAndPassword(@RequestBody Customer customer) {//<?>반환값의 클래스명이 정해져있지 않다는 뜻
Customer cus = customerRepository.findByUsernameAndPassword(customer.getUsername(), customer.getPassword());
return new ResponseEntity<>(cus, HttpStatus.OK);
}
@GetMapping("/customer/user/{username}")
public ResponseEntity<?> getByUsername(@PathVariable String username){
Customer cus = customerRepository.findByUsernameIs(username);
return new ResponseEntity<>(cus, HttpStatus.OK);
}
@GetMapping("/customer/{age}")
public ResponseEntity<?> findByAgeGreaterThanEqual(@PathVariable int age){
List<Customer> cus = customerRepository.findByAgeGreaterThanEqual(age);
return new ResponseEntity<>(cus, HttpStatus.OK);
}
}
[ 사용자 정의 쿼리 JPQL(Java Persistence Query Language) - Entity기준으로 만드냐 or Table기준으로 만드냐 ]
- 쿼리스트링 쓸 때 ?1 ?2 첫번째값은 1 붙여주고 두번째값은 2 붙여줘서 사용해야함
- Table 기준으로 만드는 사용자 정의 쿼리는 : Value과 nativeQuery(기본값 false) 사용
public interface CustomerRepository extends JpaRepository<Customer, Long> {
//3. 사용자 정의 쿼리 -> JPQL(Java Persistence Query Language) - Entity기준으로 만드냐
@Query("select cust from Customer cust where cust.grade=:grade")
public List<Customer> getGrade(@Param("grade") String grade);
//3. 사용자 정의 쿼리 -> JPQL(Java Persistence Query Language) - Table기준으로 만드냐
@Query(value = "select * from customer where grade=?1 and name?2", nativeQuery = true)
public List<Customer> getGrade(@Param("grade") String grade);
@Query(value = "select * from customer cust where cust.username=?1 and cust.password=?2", nativeQuery = true)
public Customer getUsernameAndPassword(String username, String password);
}
@RestController
@RequestMapping("/api")
public class CustomerController {
@Autowired
private CustomerRepository customerRepository;
@GetMapping("/customer/{grade}")
public ResponseEntity<?> getGrade(@PathVariable String grade){
List<Customer> cus = customerRepository.getGrade(grade);
return new ResponseEntity<>(cus, HttpStatus.OK);
}
}
[ 동적 쿼리 처리를 위한 Querydsl - API를 사용 ]
- 환경설정 : build.gradle에 의존성 추가 , config 패키지 생성 후 @Configuration과 @RequiredArgsConstructor 지정, @Bean
- CustomerDSLRepository에 @Repository와 @RequiredArgsConstructor지정 후 쿼리 작성
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
package com.example.jpa.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
public class QueryDSLConfig {
private final EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
- build -> generated -> sources -> annotationProcessor -> QCustomer 생성 -> 자동으로 쿼리 DSL문 생성됨 그걸 이용
package com.example.jpa.repository;
import com.example.jpa.entity.Customer;
import com.example.jpa.entity.QCustomer;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor
public class CustomerDSLRepository {
private final JPAQueryFactory queryFactory;
private final JPAQueryFactory jpaQueryFactory;
public Customer getUsernameAndPassword(String username, String password) {
QCustomer customer = QCustomer.customer;
System.out.println("execute");
return jpaQueryFactory.selectFrom(customer)
.where(customer.username.eq(username)
.and(customer.password.eq(password)))
.fetchOne();
}
public List<Customer> getGrade(String grade) {
QCustomer customer = QCustomer.customer;
return jpaQueryFactory.selectFrom(customer)
.where(customer.grade.eq(grade))
.fetch();
}
}
@RestController
@RequestMapping("/api")
public class CustomerController {
@Autowired
CustomerDSLRepository customerDSLRepository;
@PostMapping("/customer")
public ResponseEntity<?> getUsernameAndPassword(@RequestBody Customer customer) {//<?>반환값의 클래스명이 정해져있지 않다는 뜻
Customer cus = customerRepository.findByUsernameAndPassword(customer.getUsername(), customer.getPassword());
return new ResponseEntity<>(cus, HttpStatus.OK);
}
@GetMapping("/customer/{grade}")
public ResponseEntity<?> getGrade(@PathVariable String grade){
List<Customer> cus = customerDSLRepository.getGrade(grade);
return new ResponseEntity<>(cus, HttpStatus.OK);
}
}