Skip to content

Commit 16e30a8

Browse files
committed
Specification API
* hibernate metamodel generator added * Specification example is added
1 parent d4b393e commit 16e30a8

8 files changed

Lines changed: 179 additions & 16 deletions

File tree

jpa-specification/pom.xml

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
<spring.boot.version>2.0.4.RELEASE</spring.boot.version>
1818
<hamcrest-version>1.3</hamcrest-version>
1919
<mapstruct.version>1.2.0.Final</mapstruct.version>
20+
<hibernate.jpamodelgen-version>5.3.2.Final</hibernate.jpamodelgen-version>
2021

21-
<maven.plugin.compiler.version>3.6.1</maven.plugin.compiler.version>
22+
<maven.plugin.compiler.version>3.7.0</maven.plugin.compiler.version>
2223
<maven.plugin.build-helper.version>3.0.0</maven.plugin.build-helper.version>
24+
<maven.plugin.processor.version>3.2.0</maven.plugin.processor.version>
2325

2426
</properties>
2527

@@ -106,6 +108,11 @@
106108
<version>${mapstruct.version}</version>
107109
</dependency>
108110

111+
<dependency>
112+
<groupId>com.fasterxml.jackson.datatype</groupId>
113+
<artifactId>jackson-datatype-jsr310</artifactId>
114+
</dependency>
115+
109116
</dependencies>
110117

111118
<build>
@@ -119,6 +126,8 @@
119126
<configuration>
120127
<source>${java-version}</source>
121128
<target>${java-version}</target>
129+
<encoding>UTF-8</encoding>
130+
122131
<annotationProcessorPaths>
123132
<path>
124133
<groupId>org.mapstruct</groupId>
@@ -153,6 +162,34 @@
153162
</execution>
154163
</executions>
155164
</plugin>
165+
166+
<plugin>
167+
<groupId>org.bsc.maven</groupId>
168+
<artifactId>maven-processor-plugin</artifactId>
169+
<version>${maven.plugin.processor.version}</version>
170+
<executions>
171+
<execution>
172+
<id>process</id>
173+
<goals>
174+
<goal>process</goal>
175+
</goals>
176+
<phase>generate-sources</phase>
177+
<configuration>
178+
<processors>
179+
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
180+
</processors>
181+
<outputDirectory>target/generated-sources/annotations</outputDirectory>
182+
</configuration>
183+
</execution>
184+
</executions>
185+
<dependencies>
186+
<dependency>
187+
<groupId>org.hibernate</groupId>
188+
<artifactId>hibernate-jpamodelgen</artifactId>
189+
<version>${hibernate.jpamodelgen-version}</version>
190+
</dependency>
191+
</dependencies>
192+
</plugin>
156193
</plugins>
157194
</build>
158195

jpa-specification/src/main/java/com/fd/jpa/controller/PersonController.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,24 @@
1414

1515
import com.fd.jpa.converter.CycleAvoidingMappingContext;
1616
import com.fd.jpa.converter.PersonEntityMapper;
17-
import com.fd.jpa.entity.PersonEntityModel;
17+
import com.fd.jpa.entity.PersonEntity;
1818
import com.fd.jpa.model.Person;
19+
import com.fd.jpa.repository.person.PersonRepository;
20+
import com.fd.jpa.repository.person.PersonSpecifications;
1921
import lombok.extern.slf4j.Slf4j;
2022
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.data.jpa.domain.Specification;
2124
import org.springframework.web.bind.annotation.GetMapping;
25+
import org.springframework.web.bind.annotation.PathVariable;
2226
import org.springframework.web.bind.annotation.PostMapping;
2327
import org.springframework.web.bind.annotation.RequestBody;
2428
import org.springframework.web.bind.annotation.RequestMapping;
29+
import org.springframework.web.bind.annotation.RequestParam;
2530
import org.springframework.web.bind.annotation.RestController;
2631

2732
import javax.servlet.http.HttpServletRequest;
28-
import java.time.LocalDate;
33+
import java.util.List;
34+
import java.util.Optional;
2935

3036
/**
3137
* @author furkan.danismaz
@@ -39,16 +45,32 @@ public class PersonController extends BaseController {
3945
@Autowired
4046
private PersonEntityMapper personEntityMapper;
4147

48+
@Autowired
49+
private PersonRepository personRepository;
50+
4251
@GetMapping("/{id}")
43-
public Person getPerson() {
44-
return new Person(1, "furkan", "danismaz", LocalDate.of(1985, 12, 7));
52+
public Person getPerson(@PathVariable int id) {
53+
Optional<PersonEntity> queryResult = this.personRepository.findById(id);
54+
if (queryResult.isPresent()) {
55+
return this.personEntityMapper.toBusinessObject(queryResult.get(), new CycleAvoidingMappingContext(), this.getRequestTimeZone());
56+
}
57+
return null;
58+
}
59+
60+
@GetMapping("/search")
61+
public List<Person> search(@RequestParam String name, @RequestParam String surname) {
62+
List<PersonEntity> searchResult = this.personRepository.findAll(
63+
Specification.where(PersonSpecifications.withName(name))
64+
.and(PersonSpecifications.withSurname(surname)));
65+
return this.personEntityMapper.toBusinessObjectList(searchResult, new CycleAvoidingMappingContext());
4566
}
4667

4768
@PostMapping
4869
public Person savePerson(@RequestBody Person person, HttpServletRequest request) {
49-
PersonEntityModel personEntityModel = this.personEntityMapper.toEntityModel(person, new CycleAvoidingMappingContext(), this.getRequestTimeZone());
50-
log.debug(personEntityModel.toString());
51-
return null;
70+
PersonEntity personEntity = this.personEntityMapper.toEntity(person, new CycleAvoidingMappingContext(), this.getRequestTimeZone());
71+
this.personRepository.save(personEntity);
72+
person.setId(personEntity.getId());
73+
return person;
5274
}
5375

5476
}

jpa-specification/src/main/java/com/fd/jpa/converter/PersonEntityMapper.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212
*/
1313
package com.fd.jpa.converter;
1414

15-
import com.fd.jpa.entity.PersonEntityModel;
15+
import com.fd.jpa.entity.PersonEntity;
1616
import com.fd.jpa.model.Person;
1717
import org.mapstruct.Context;
1818
import org.mapstruct.Mapper;
1919

20+
import java.util.List;
2021
import java.util.TimeZone;
2122

2223
/**
@@ -26,11 +27,17 @@
2627
@Mapper(config = EntityMapperConfig.class, componentModel = "spring")
2728
public interface PersonEntityMapper {
2829

29-
Person toBusinessModel(PersonEntityModel entityModel,
30-
@Context CycleAvoidingMappingContext context,
31-
@Context TimeZone timeZone);
30+
Person toBusinessObject(PersonEntity entity,
31+
@Context CycleAvoidingMappingContext context,
32+
@Context TimeZone timeZone);
33+
34+
PersonEntity toEntity(Person bo,
35+
@Context CycleAvoidingMappingContext context,
36+
@Context TimeZone timeZone);
37+
38+
39+
List<PersonEntity> toEntityList(List<Person> boList, @Context CycleAvoidingMappingContext context);
40+
41+
List<Person> toBusinessObjectList(List<PersonEntity> entityList, @Context CycleAvoidingMappingContext context);
3242

33-
PersonEntityModel toEntityModel(Person p,
34-
@Context CycleAvoidingMappingContext context,
35-
@Context TimeZone timeZone);
3643
}

jpa-specification/src/main/java/com/fd/jpa/entity/PersonEntityModel.java renamed to jpa-specification/src/main/java/com/fd/jpa/entity/PersonEntity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
@Data
2727
@Entity
2828
@Table(name = "PEOPLE")
29-
public class PersonEntityModel extends EntityModel {
29+
public class PersonEntity extends EntityModel {
3030

3131
@Column(name = "NAME")
3232
private String name;

jpa-specification/src/main/java/com/fd/jpa/model/Person.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
package com.fd.jpa.model;
1414

15+
import com.fasterxml.jackson.annotation.JsonFormat;
1516
import lombok.AllArgsConstructor;
1617
import lombok.Data;
1718
import lombok.NoArgsConstructor;
@@ -30,6 +31,8 @@ public class Person {
3031
private int id;
3132
private String name;
3233
private String surname;
34+
35+
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy")
3336
private LocalDate birthdate;
3437

3538
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Telif hakkı 2017 Türkiye Bilimsel ve Teknolojik Araştırma Kurumu.
3+
* Tüm haklar saklıdır.
4+
*
5+
* BU TELİF HAKKI DOSYA ÜST BİLGİSİNİ DEĞİŞTİRMEYİNİZ VEYA SİLMEYİNİZ.
6+
*
7+
* Bu kaynak kod sadece TÜBİTAK için TYBS Projesi kapsamında geliştirilmiştir;
8+
* değişiklik yapma, başka amaçlarda kullanılmak üzere kısmen veya tamamını
9+
* kopyalama ve/veya dağıtım yapma hakkınız bulunmamaktadır.
10+
*
11+
* Daha fazla bilgi ve sorularınız için TÜBİTAK ile iletişime geçiniz.
12+
*/
13+
package com.fd.jpa.repository;
14+
15+
import com.fd.jpa.entity.EntityModel;
16+
import org.springframework.data.jpa.repository.JpaRepository;
17+
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
18+
19+
/**
20+
* @author furkan.danismaz
21+
* 11/09/2018 14:54
22+
*/
23+
public interface GenericRepository<T extends EntityModel> extends JpaRepository<T, Integer>, JpaSpecificationExecutor<T> {
24+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Telif hakkı 2017 Türkiye Bilimsel ve Teknolojik Araştırma Kurumu.
3+
* Tüm haklar saklıdır.
4+
*
5+
* BU TELİF HAKKI DOSYA ÜST BİLGİSİNİ DEĞİŞTİRMEYİNİZ VEYA SİLMEYİNİZ.
6+
*
7+
* Bu kaynak kod sadece TÜBİTAK için TYBS Projesi kapsamında geliştirilmiştir;
8+
* değişiklik yapma, başka amaçlarda kullanılmak üzere kısmen veya tamamını
9+
* kopyalama ve/veya dağıtım yapma hakkınız bulunmamaktadır.
10+
*
11+
* Daha fazla bilgi ve sorularınız için TÜBİTAK ile iletişime geçiniz.
12+
*/
13+
package com.fd.jpa.repository.person;
14+
15+
import com.fd.jpa.entity.PersonEntity;
16+
import com.fd.jpa.repository.GenericRepository;
17+
18+
/**
19+
* @author furkan.danismaz
20+
* 11/09/2018 14:53
21+
*/
22+
public interface PersonRepository extends GenericRepository<PersonEntity> {
23+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Telif hakkı 2017 Türkiye Bilimsel ve Teknolojik Araştırma Kurumu.
3+
* Tüm haklar saklıdır.
4+
*
5+
* BU TELİF HAKKI DOSYA ÜST BİLGİSİNİ DEĞİŞTİRMEYİNİZ VEYA SİLMEYİNİZ.
6+
*
7+
* Bu kaynak kod sadece TÜBİTAK için TYBS Projesi kapsamında geliştirilmiştir;
8+
* değişiklik yapma, başka amaçlarda kullanılmak üzere kısmen veya tamamını
9+
* kopyalama ve/veya dağıtım yapma hakkınız bulunmamaktadır.
10+
*
11+
* Daha fazla bilgi ve sorularınız için TÜBİTAK ile iletişime geçiniz.
12+
*/
13+
package com.fd.jpa.repository.person;
14+
15+
import com.fd.jpa.entity.PersonEntity;
16+
import com.fd.jpa.entity.PersonEntity_;
17+
import org.springframework.data.jpa.domain.Specification;
18+
19+
import javax.persistence.criteria.CriteriaBuilder;
20+
import javax.persistence.criteria.CriteriaQuery;
21+
import javax.persistence.criteria.Predicate;
22+
import javax.persistence.criteria.Root;
23+
24+
/**
25+
* @author furkan.danismaz
26+
* 11/09/2018 16:41
27+
*/
28+
public class PersonSpecifications {
29+
30+
public static Specification<PersonEntity> withName(String name) {
31+
return new Specification<PersonEntity>() {
32+
@Override
33+
public Predicate toPredicate(Root<PersonEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
34+
return criteriaBuilder.equal(root.get(PersonEntity_.name), name);
35+
}
36+
};
37+
}
38+
39+
public static Specification<PersonEntity> withSurname(String surname) {
40+
return new Specification<PersonEntity>() {
41+
@Override
42+
public Predicate toPredicate(Root<PersonEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
43+
return criteriaBuilder.equal(root.get(PersonEntity_.surname), surname);
44+
}
45+
};
46+
}
47+
}

0 commit comments

Comments
 (0)