Skip to content

Commit 1e54f7b

Browse files
committed
Merge branch '2.1.4.1.RELEASE'
2 parents f4c04d6 + 7f512e3 commit 1e54f7b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+4133
-2
lines changed

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,16 @@
2121

2222
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2323
hs_err_pid*
24+
25+
# Maven
26+
target/
27+
28+
# MacOS
29+
.DS_Store
30+
31+
32+
# Eclipse
33+
.project
34+
.classpath
35+
.springBeans
36+
.settings/

README.adoc

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
= spring-data-rest-jpa-specification
2+
3+
== Installation (POM)
4+
[source,xml,indent=1]
5+
----
6+
<repository>
7+
<id>u2ware-mvm-repo</id>
8+
<url>https://raw.github.com/u2ware/u2ware.github.com/mvn-repo/</url>
9+
</repository>
10+
11+
<dependency>
12+
<groupId>io.github.u2ware</groupId>
13+
<artifactId>spring-data-rest-jpa-specification</artifactId>
14+
<version>2.1.4.1.RELEASE</version>
15+
</dependency>
16+
----
17+
18+
*spring-data-rest-specification* 는
19+
https://docs.spring.io/spring-boot/docs/2.1.4.RELEASE/reference/htmlsingle/[spring-boot-2.1.4.RELEASE] ,
20+
기반으로 동작합니다.
21+
22+
23+
== PredicateBuilder
24+
25+
*spring-data-rest-specification* 는 link:https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/api/org/springframework/data/jpa/domain/Specification.html[Specification] 를 작성하기 위해
26+
link:./src/main/java/org/springframework/data/jpa/repository/query/PredicateBuilder.java[PredicateBuilder]
27+
를 제공합니다.
28+
29+
[source,java,indent=1]
30+
----
31+
32+
import org.springframework.data.jpa.domain.Specification;
33+
import org.springframework.data.jpa.repository.query.PredicateBuilder;
34+
35+
public class PeopleQuery implements Specification<People>{
36+
37+
private String name;
38+
private String firstName;
39+
private String lastName;
40+
private Integer age;
41+
42+
@Override
43+
public class Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
44+
return new PredicateBuilder()
45+
.eq("name", age) // age 가 null 일 경우 이 where 조건은 반영되지 않습니다.
46+
.eq("age", age) // age 가 null 일 경우 이 where 조건은 반영되지 않습니다.
47+
.eq("firstName", firstName, Handler.IGNORE_CASE) // 대소문자를 구분하지 않고 검색합니다.
48+
.like("lastName", lastName, Handler.CONTAINING) //검색 파라미터에 값에 % 를 앞뒤로 붙혀서 검색합니다.
49+
.in(...)
50+
.gt(...) //greater then
51+
.gte(...) //greater then or equals
52+
.lt(...) //less then
53+
.lte(...) //less then or equals
54+
.build(root, query, cb);
55+
}
56+
----
57+
58+
== JpaSpecification
59+
60+
*spring-data-rest-specification* 는 link:https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/api/org/springframework/data/jpa/domain/Specification.html[Specification] 를 생성하기 위해
61+
link:./src/main/java/org/springframework/data/jpa/repository/query/JpaSpecification.java[JpaSpecification]
62+
를 제공합니다.
63+
64+
[source,java,indent=1]
65+
----
66+
67+
import org.springframework.data.jpa.repository.query.JpaSpecification;
68+
69+
public class PeopleService{
70+
71+
private @Autowired PepleRepository pepleRepository;
72+
73+
public List<People> findBy(MultiValueMap<String,Object> params) {
74+
75+
return pepleRepository.findAll(JpaSpecification.of(params, "findByNameAndAge"));
76+
}
77+
}
78+
----
79+
80+
== The dynamic query method resource
81+
82+
https://docs.spring.io/spring-data/rest/docs/3.1.6.RELEASE/reference/html/#repository-resources.query-method-resource[spring-data-rest] 는
83+
아래와 같이 정의된 https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/reference/html/#repositories.query-methods.query-creation[Query Method] 에 대해
84+
_/people/search/findByNameStartsWith_ 주소로 Resource 를 제공하는것으로 알려져 있습니다.
85+
[source,java,indent=1]
86+
----
87+
// --> /people/search/findByNameStartsWith
88+
public interface PeopleRepository extends PagingAndSortingRepository<People,Long>{
89+
90+
public Page findByNameStartsWith(@Param("name") String name, Pageable p);
91+
92+
}
93+
----
94+
95+
*spring-data-rest-specification* 는
96+
https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/api/org/springframework/data/jpa/repository/JpaSpecificationExecutor.html[JpaSpecificationExecutor]
97+
를 확장한 Repository 기준으로 다음과 같은 hypermedia-driven HTTP resources 를 제공합니다.
98+
99+
* `/{repository}/!q/{queryMethod}`
100+
* `/{repository}/!q?q={queryMethod}`
101+
102+
즉, 인터페이스에 메소드 선언이 없더라도 동적으로 https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/reference/html/#repositories.query-methods.query-creation[Query Method] 기반의 여러 Resource 를 사용할 수 있습니다.
103+
104+
[source,java,indent=1]
105+
----
106+
107+
// --> /peoples/!q/findByNameStartsWith
108+
// --> /peoples/!q?q=findByNameStartsWith
109+
// --> /peoples/!q/findByBirthday
110+
// --> /peoples/!q?q=findByBirthday
111+
// --> /peoples/!q/findByNameAndAge
112+
// --> /peoples/!q?q=findByNameAndAge
113+
// --> ...
114+
// --> ...
115+
public interface PeopleRepository extends PagingAndSortingRepository<People,Long>,
116+
JpaSpecificationExecutor<People> { // **
117+
118+
119+
}
120+
----
121+
또한, parameter 값의 존재 여부에 따라 where 조건이 동적으로 제거 됩니다.
122+
123+
|===
124+
|요청주소 및 파라미터 | 실행되는 Query Method
125+
126+
| /peoples/!q/findByNameAndAge?name=홍길동&age=16
127+
| findByNameAndAge(....){}
128+
129+
| /peoples/!q/findByNameAndAge?name=홍길동
130+
| findByName(....){}
131+
132+
| /peoples/!q/findByNameAndAge?age=홍길동
133+
| findByAge(....){}
134+
135+
| /peoples/!q/findByNameAndAge
136+
| findAll(....){}
137+
|===
138+
139+
== The specification based resource
140+
141+
*spring-data-rest-specification* 는
142+
* `/{repository}/!q/{spcificationImplClassName}`
143+
* `/{repository}/!q?q={spcificationImplClassName}`
144+
와 같은 Resource 를 제공합니다.
145+
146+
https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/api/org/springframework/data/jpa/domain/Specification.html[Specification] 를 구현한 클래스가 존재한다면, 해당 클래스 이름으로 Resource 를 사용할 수 있습니다.
147+
148+
[source,java,indent=1]
149+
----
150+
package com.mycompany;
151+
152+
// --> /peoples/!q/com.mycompany.MyPeopleSpecification
153+
public class MyPeopleSpecification implements Specification<People>{
154+
155+
@Override
156+
public Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
157+
...
158+
}
159+
}
160+
161+
// --> /peoples/!q/com.mycompany.YourPeopleSpecification
162+
public class YourPeopleSpecification implements Specification<People>{
163+
@Override
164+
public Predicate toPredicate(Root<People> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
165+
...
166+
}
167+
}
168+
----
169+
170+
== Events based Resource
171+
172+
*spring-data-rest-specification* 는
173+
174+
* `/{repository}/!q`
175+
176+
와 같은 기본 Resource 를 제공합니다.
177+
178+
기본적으로 findAll 과 같은 리소스를 리턴하지만,
179+
link:./src/main/java/org/springframework/data/rest/core/event/RepositoryRestEventHandler.java[RepositoryRestEventHandler]
180+
빈이 정의 되어 있다면, 다음과 같이 MyPeopleHandler 의 handleBeforeRead 를 이용하여,
181+
`/{repository}/!q` 리소스에 검색 조건을 추가할 수 있습니다.
182+
183+
184+
[source,java,indent=1]
185+
----
186+
// --> /peoples/!q
187+
@Component
188+
public class MyPeopleHandler extends RepositoryRestEventHandler<People>{ //**
189+
190+
@Override
191+
public void handleBeforeRead(JpaSpecification<People> spec) {
192+
193+
Pepole params = spec.getPayload();
194+
195+
spec.getPredicateBuilder().eq("name", params.getName())
196+
.like(...)
197+
...
198+
199+
}
200+
}
201+
----
202+
203+
다음과 같이
204+
link:./src/main/java/org/springframework/data/rest/core/annotation/HandleBeforeRead.java[@HandleBeforeRead]
205+
을 사용하여 기술할수도 있습니다.
206+
207+
[source,java,indent=1]
208+
----
209+
210+
@Component
211+
@RepositoryEventHandler(People.class) //**
212+
public class MyPeopleHandler {
213+
214+
@HandleBeforeRead // --> /peoples/!q
215+
public void handleBeforeRead(JpaSpecification<People> spec) {
216+
217+
Pepole params = spec.getPayload();
218+
219+
spec.getPredicateBuilder().eq("name", params.getName())
220+
.like(...)
221+
...
222+
}
223+
224+
@HandleAfterCreate
225+
public void handleAfterCreate(People entity) {
226+
... logic to handle inspecting the entity before the Repository saves it
227+
}
228+
229+
@HandleAfterDelete
230+
public void handleAfterDelete(People entity) {
231+
... send a message that this entity has been delete
232+
}
233+
}
234+
----
235+
236+
237+
== Method level security
238+
239+
240+
`/{repository}/!q/{queryMethod Or spcificationImplClassName}` 에 대해 method level security 를 설정할 수 있습니다.
241+
242+
[source,java,indent=1]
243+
----
244+
@Configuration
245+
@EnableWebSecurity
246+
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) // **
247+
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
248+
...
249+
}
250+
251+
public interface PeopleRepository extends PagingAndSortingRepository<People,Long>,
252+
JpaSpecificationExecutor<People> {
253+
254+
@PreAuthorize("hasRole('ROLE_ADMIN')") // **
255+
@Override
256+
Page<People> findAll(Specification<People> spec, Pageable pageable);
257+
258+
}
259+
----
260+
261+
262+
== License
263+
spring-data-rest-specification is Open Source software released under the
264+
http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].

README.md

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)