/spring-data-rest-jpa-specification

This project has closed. Move to https://github.com/u2ware/u2ware-data-rest/

Primary LanguageJavaApache License 2.0Apache-2.0

This project has closed. Move to u2ware-data-rest.

이 프로젝트는 종료되었습니다. u2ware-data-rest 로 이관하였습니다.

spring-data-rest-jpa-specification

Installation (POM)

 <repository>
     <id>u2ware-mvm-repo</id>
     <url>https://raw.github.com/u2ware/u2ware.github.com/mvn-repo/</url>
 </repository>

 <dependency>
     <groupId>io.github.u2ware</groupId>
     <artifactId>spring-data-rest-jpa-specification</artifactId>
     <version>2.1.5.3.RELEASE</version>
 </dependency>

PredicateBuilder

spring-data-rest-jpa-specificationSpecification 를 작성하기 위해 PredicateBuilder 를 제공합니다.

 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.data.jpa.repository.query.PredicateBuilder;

 public class PeopleQuery implements Specification<People>{

     private String name;
     private String firstName;
     private String lastName;
     private Integer age;

     @Override
     public class Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
         return new PredicateBuilder(root,query,cb)
                     .and().eq("name", name) // name 이(가) null 일 경우 이 where 조건은 반영되지 않습니다.
                     .andStart()
                     	.eq("firstName", lastName)
                     	.or()
                     	.eq("lastName", lastName)
                     .andEnd()
                     .and().like(...)
                     .and().in(...)
                     .and().gt(...)   //greater then
                     .and().gte(...)  //greater then or equals
                     .and().lt(...)   //less then
                     .and().lte(...)  //less then or equals
                     .order().asc("name")
                     .order().desc("age")
                     .build();
     }
 }

PartTreeSpecification

spring-data-rest-jpa-specificationSpecification 를 생성하기 위해 PartTreeSpecification 를 제공합니다.

 import org.springframework.data.jpa.repository.query.JpaSpecification;

 public class PeopleService{

 	private @Autowired PepleRepository  pepleRepository;

 	public List<People> findBy(MultiValueMap<String,Object> params) {

 		Specification spec = new PartTreeSpecification("findByNameAndAge", params);
 		return pepleRepository.findAll(spec);
 	}
 }

The dynamic query method resource

spring-data-rest 는 아래와 같이 정의된 Query Method 에 대해 /people/search/findByNameStartsWith 주소로 Resource 를 제공하는것으로 알려져 있습니다.

 // --> /people/search/findByNameStartsWith
 public interface PeopleRepository extends PagingAndSortingRepository<People,Long>{

     public Page findByNameStartsWith(@Param("name") String name, Pageable p);

 }

spring-data-rest-jpa-specificationJpaSpecificationExecutor 를 확장한 Repository 기준으로 다음과 같은 hypermedia-driven HTTP resources 를 제공합니다.

  • /{repository}/!q/{queryMethod}

  • /{repository}/!q?q={queryMethod}

즉, 인터페이스에 메소드 선언이 없더라도 동적으로 Query Method 기반의 여러 Resource 를 사용할 수 있습니다.

 // --> /peoples/!q/findByNameStartsWith
 // --> /peoples/!q?q=findByNameStartsWith
 // --> /peoples/!q/findByBirthday
 // --> /peoples/!q?q=findByBirthday
 // --> /peoples/!q/findByNameAndAge
 // --> /peoples/!q?q=findByNameAndAge
 // --> ...
 // --> ...
 public interface PeopleRepository extends PagingAndSortingRepository<People,Long>,
                                           JpaSpecificationExecutor<People> {  // **


 }

또한, parameter 값의 존재 여부에 따라 where 조건이 동적으로 제거 됩니다.

요청주소 및 파라미터 실행되는 Query Method

/peoples/!q/findByNameAndAge?name=홍길동&age=16

findByNameAndAge(…​.){}

/peoples/!q/findByNameAndAge?name=홍길동

findByName(…​.){}

/peoples/!q/findByNameAndAge?age=홍길동

findByAge(…​.){}

/peoples/!q/findByNameAndAge

findAll(…​.){}

The specification based resource

spring-data-rest-jpa-specification 는 * /{repository}/!q/{spcificationImplClassName} * /{repository}/!q?q={spcificationImplClassName} 와 같은 Resource 를 제공합니다.

Specification 를 구현한 클래스가 존재한다면, 해당 클래스 이름으로 Resource 를 사용할 수 있습니다.

 package com.mycompany;

 // --> /peoples/!q/com.mycompany.MyPeopleSpecification
 public class MyPeopleSpecification implements Specification<People>{

     @Override
     public Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
         ...
     }
 }

 // --> /peoples/!q/com.mycompany.YourPeopleSpecification
 public class YourPeopleSpecification implements Specification<People>{
     @Override
     public Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
         ...
     }
 }

Resource Events

spring-data-rest-jpa-specification/{repository}/!q 에 대해 Event 를 발생합니다.

RepositoryRestEventHandler 빈이 정의 되어 있다면, 다음과 같이 MyPeopleHandler 의 handleBeforeRead 를 이용하여, /{repository}/!q 리소스에 검색 조건을 추가할 수 있습니다.

 // --> /peoples/!q
 @Component
 public class MyPeopleHandler extends RepositoryRestEventHandler<People>{  //**

 	@Override
 	public void handlePredicateBuilder(PredicateBuilder<People> builder) {

         People entity = builder.getRequestParamToEntity();

 		builder.and().eq("name", entity.getName())
 		       .and().like(...)
 		       ...

 	}

 	@Override
 	public void handleAfterCreate(People entity) {
 		... logic to handle inspecting the entity before the Repository saves it
 	}

 	@Override
 	public void handleAfterDelete(People entity) {
 		... send a message that this entity has been delete
 	}
 }

다음과 같이 @HandlePredicateBuilder 을 사용하는 방법도 있습니다.

 @Component
 @RepositoryEventHandler(People.class) //**
 public class MyPeopleHandler {

 	@HandlePredicateBuilder // --> /peoples/!q
 	public void handlePredicateBuilder(PredicateBuilder<People> builder) {

         MultiValueMap<String,Object> params = builder.getRequestParam();

 		builder.and().eq("age", params.getFirst("age"))
 		       .and().like(...)
 		       ...
 	}

 }

Method level security

/{repository}/!q/{queryMethod Or spcificationImplClassName} 에 대해 method level security 를 설정할 수 있습니다.

 @Configuration
 @EnableWebSecurity
 @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) // **
 public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
     ...
 }

 public interface PeopleRepository extends PagingAndSortingRepository<People,Long>,
                                           JpaSpecificationExecutor<People> {

     @PreAuthorize("hasRole('ROLE_ADMIN')")  // **
     @Override
     Page<People> findAll(Specification<People> spec, Pageable pageable);

 }

License

spring-data-rest-jpa-specification is Open Source software released under the Apache 2.0 license.