Skip to content

Commit 7a9b1ef

Browse files
committed
2.1.4.1.RELEASE
1 parent f4c04d6 commit 7a9b1ef

Some content is hidden

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

57 files changed

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