public interface MyEntityRepository extends JpaRepository<MyEntity, KeyClass>, MyEntityRepositoryCustom {
}
QueryDslPredicateExecutor를 추가하지 않아도 된다. Custom 에서 QueryDslJpaRepository를 구현해서 직접 사용해도 된다.JpaRepository, QueryDslJpaRepository, JpaSpecificationExecutor 등을 조합하고자 할 경우에 이것들을 통합 상속하는 인터페이스를 만들고 JpaRepository 대신 이를 extends 해도 된다.@Transactional(value = "transactionManager", readOnly = false) public abstract class MyDomainRepositorySupport extends QueryDslRepositorySupport { // JdbcTemplate, jooq 등을 injection할 수도 있다. public MyDomainRepositorySupport(Class<?> domainClass) { super(domainClass); } @PersistenceContext(unitName = "persistenceUnitName") @Override public void setEntityManager(EntityManager entityManager) { super.setEntityManager(entityManager); } }
@Transactional을 붙여야 한다.autocommit=false가 기본으로 하고 작업시마다 autocommit=false|true 토글을 하지 않고 hibernate.connection.provider_disables_autocommit: true 인 경우에 문제가 된다.@Transactional을 붙여야한다.
BoardRepository가 도메인 모듈에 있을 때, API 모듈에서 이를 상속해서 BoardApiRepository 처럼 만들거나 하는 경우가 발견됨. 절대 상속하지 말 것Pageable 을 인자로 받는 메소드는 기본적으로 전체 갯수를 세는 쿼리를 추가로 요청한다.Pageable 과 달리 전체 갯수를 세지 않는다.Slice 를 이용해 페이지 데이터를 가져오게 한다.Slice 도 offset/limit 방식으로 성능이 떨어지는 것은 동일하다.@Query(value = "select user_id, user_name from users ", nativeQuery = true) List<Object[]> findUSBCandidates();
@Query(value=“쿼리문”, nativeQuery = true)로 수행한다.Object []로 받아서 컬럼 지정 순서대로 값을 뽑아서 사용한다.@Query 결과를 Projection 하려면 Value Object의 필드 이름과 동일하게 alias 하여 컬럼을 select 한다.QueryDslRepositorySupport을 상속하면 QueryDSL 사용이 가능해진다.QuerydslRepositorySupport 로 이름 변경QueryDslRepositorySupport 상속 객체를 Spy() 로 만들고 repositoryImpl.from(_) » jpqlQuery 로 한 뒤에 jpqlQuery에 대해 행위를 정의하면 된다.java extension으로 추가한다.#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end import org.springframework.stereotype.Repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.querydsl.QueryDslPredicateExecutor; #parse("File Header.java") @Repository public interface ${EntityClass}Repository extends JpaRepository<${EntityClass}, ${EntityKey}>, QuerydslPredicateExecutor<${EntityClass}>, ${EntityClass}RepositoryCustom { }
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end import org.springframework.data.jpa.repository.support.QueryDslRepositorySupport; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; public class ${EntityClass}RepositoryImpl extends QuerydslRepositorySupport implements ${EntityClass}RepositoryCustom { public ${EntityClass}RepositoryImpl() { super(${EntityClass}.class); } @PersistenceContext @Override public void setEntityManager(EntityManager entityManager) { super.setEntityManager(entityManager); } }
Optional, CompletableFuture, Stream 등 지원CompletableFuture, Stream 사용시에 Transaction Boundary 조심할 것.interface CustomerRepository extends Repository<Customer, Long> { @Async CompletableFuture<List<Customer>> readAllBy(); @Query("select c from Customer c") Stream<Customer> streamAllCustomers(); // CRUD method using Optional Optional<Customer> findOne(Long id); // Query method using Optional Optional<Customer> findByLastname(String lastname); }
existsByXXX 형태의 메소드로 가능.Repository.exists(example) 가능? is null or 비교 를 붙이면 된다.(? IS NULL OR COLUMN = ?)
@Query("select u from User u where u.age = ?#{[0]}") List<User> findUsersByAge(int age); @Query("select u from User u where u.firstname = :#{#customer.firstname}") List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);