JAVA-11535 Move spring-data related modules to persistence-modules (#12126)
This commit is contained in:
6
persistence-modules/spring-data-rest-querydsl/README.md
Normal file
6
persistence-modules/spring-data-rest-querydsl/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## Spring Data REST Querydsl
|
||||
|
||||
This module contains articles about Querydsl with Spring Data REST
|
||||
|
||||
### Relevant Articles:
|
||||
- [REST Query Language Over Multiple Tables with Querydsl Web Support](https://www.baeldung.com/rest-querydsl-multiple-tables)
|
||||
109
persistence-modules/spring-data-rest-querydsl/pom.xml
Normal file
109
persistence-modules/spring-data-rest-querydsl/pom.xml
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>spring-data-rest-querydsl</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>spring-data-rest-querydsl</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-apt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.querydsl</groupId>
|
||||
<artifactId>querydsl-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>${start-class}</mainClass>
|
||||
<layout>ZIP</layout>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.source}</source>
|
||||
<target>${maven.target}</target>
|
||||
<compilerArgs>
|
||||
<arg>-verbose</arg>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mysema.maven</groupId>
|
||||
<artifactId>apt-maven-plugin</artifactId>
|
||||
<version>${mysema.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>process</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory>
|
||||
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.source>1.8</maven.source>
|
||||
<maven.target>1.8</maven.target>
|
||||
<mysema.version>1.1.3</mysema.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.controller.repository.AddressRepository;
|
||||
import com.baeldung.controller.repository.UserRepository;
|
||||
import com.baeldung.entity.Address;
|
||||
import com.baeldung.entity.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* Note: In the IDE, remember to generate query type classes before running the Integration Test (e.g. in Eclipse right-click on the project > Run As > Maven generate sources)
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EntityScan("com.baeldung.entity")
|
||||
@EnableJpaRepositories("com.baeldung.controller.repository")
|
||||
@EnableAutoConfiguration
|
||||
public class Application {
|
||||
|
||||
@Autowired
|
||||
private UserRepository personRepository;
|
||||
@Autowired
|
||||
private AddressRepository addressRepository;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void initializeData() {
|
||||
// Create John
|
||||
final User john = new User("John");
|
||||
personRepository.save(john);
|
||||
final Address addressOne = new Address("Fake Street 1", "Spain", john);
|
||||
addressRepository.save(addressOne);
|
||||
// Create Lisa
|
||||
final User lisa = new User("Lisa");
|
||||
personRepository.save(lisa);
|
||||
final Address addressTwo = new Address("Real Street 1", "Germany", lisa);
|
||||
addressRepository.save(addressTwo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.baeldung.controller;
|
||||
|
||||
import com.baeldung.controller.repository.AddressRepository;
|
||||
import com.baeldung.controller.repository.UserRepository;
|
||||
import com.baeldung.entity.Address;
|
||||
import com.baeldung.entity.User;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.querydsl.binding.QuerydslPredicate;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class QueryController {
|
||||
|
||||
@Autowired
|
||||
private UserRepository personRepository;
|
||||
@Autowired
|
||||
private AddressRepository addressRepository;
|
||||
|
||||
@GetMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Iterable<User> queryOverUser(@QuerydslPredicate(root = User.class) Predicate predicate) {
|
||||
final BooleanBuilder builder = new BooleanBuilder();
|
||||
return personRepository.findAll(builder.and(predicate));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/addresses", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public Iterable<Address> queryOverAddress(@QuerydslPredicate(root = Address.class) Predicate predicate) {
|
||||
final BooleanBuilder builder = new BooleanBuilder();
|
||||
return addressRepository.findAll(builder.and(predicate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.controller.repository;
|
||||
|
||||
import com.baeldung.entity.Address;
|
||||
import com.baeldung.entity.QAddress;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
import com.querydsl.core.types.dsl.StringPath;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
|
||||
import org.springframework.data.querydsl.binding.QuerydslBindings;
|
||||
import org.springframework.data.querydsl.binding.SingleValueBinding;
|
||||
|
||||
public interface AddressRepository
|
||||
extends JpaRepository<Address, Long>, QuerydslPredicateExecutor<Address>, QuerydslBinderCustomizer<QAddress> {
|
||||
@Override
|
||||
default void customize(final QuerydslBindings bindings, final QAddress root) {
|
||||
bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::eq);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.controller.repository;
|
||||
|
||||
import com.baeldung.entity.QUser;
|
||||
import com.baeldung.entity.User;
|
||||
import com.querydsl.core.types.dsl.StringExpression;
|
||||
import com.querydsl.core.types.dsl.StringPath;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
|
||||
import org.springframework.data.querydsl.binding.QuerydslBindings;
|
||||
import org.springframework.data.querydsl.binding.SingleValueBinding;
|
||||
|
||||
public interface UserRepository
|
||||
extends JpaRepository<User, Long>, QuerydslPredicateExecutor<User>, QuerydslBinderCustomizer<QUser> {
|
||||
@Override
|
||||
default void customize(final QuerydslBindings bindings, final QUser root) {
|
||||
bindings.bind(String.class).first((SingleValueBinding<StringPath, String>) StringExpression::eq);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.baeldung.entity;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
|
||||
public class Address {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", unique = true, nullable = false)
|
||||
private Long id;
|
||||
@Column
|
||||
private String address;
|
||||
@Column
|
||||
private String country;
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public Address(String address, String country, User user) {
|
||||
this.id = id;
|
||||
this.address = address;
|
||||
this.country = country;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
|
||||
@Entity
|
||||
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", unique = true, nullable = false)
|
||||
private Long id;
|
||||
@Column
|
||||
private String name;
|
||||
@OneToOne(fetch = FetchType.LAZY, mappedBy = "user")
|
||||
private Address address;
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(Address address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.jdbc.Driver
|
||||
hikari:
|
||||
pool-name: hikari-pool
|
||||
url: jdbc:mysql://localhost:3306/baeldung?verifyServerCertificate=false&useSSL=false&requireSSL=false
|
||||
username: root
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: create
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.baeldung.Application;
|
||||
|
||||
/**
|
||||
* Note: In the IDE, remember to generate query type classes before running the Integration Test (e.g. in Eclipse right-click on the project > Run As > Maven generate sources)
|
||||
*
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
public class SpringContextTest {
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.baeldung.springdatarestquerydsl;
|
||||
|
||||
import com.baeldung.Application;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class) @WebAppConfiguration
|
||||
public class IntegrationTest {
|
||||
|
||||
final MediaType contentType =
|
||||
new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype());
|
||||
|
||||
@Autowired private WebApplicationContext webApplicationContext;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before public void setupMockMvc() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
|
||||
}
|
||||
|
||||
@Test public void givenRequestHasBeenMade_whenQueryOverNameAttribute_thenGetJohn() throws Exception {
|
||||
// Get John
|
||||
mockMvc.perform(get("/users?name=John")).andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", hasSize(1))).andExpect(jsonPath("$[0].name", is("John")))
|
||||
.andExpect(jsonPath("$[0].address.address", is("Fake Street 1")))
|
||||
.andExpect(jsonPath("$[0].address.country", is("Spain")));
|
||||
}
|
||||
|
||||
@Test public void givenRequestHasBeenMade_whenQueryOverNameAttribute_thenGetLisa() throws Exception {
|
||||
// Get Lisa
|
||||
mockMvc.perform(get("/users?name=Lisa")).andExpect(status().isOk()).andExpect(content().contentType(contentType))
|
||||
.andExpect(jsonPath("$", hasSize(1))).andExpect(jsonPath("$[0].name", is("Lisa")))
|
||||
.andExpect(jsonPath("$[0].address.address", is("Real Street 1")))
|
||||
.andExpect(jsonPath("$[0].address.country", is("Germany")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.baeldung.springdatarestquerydsl;
|
||||
|
||||
import com.baeldung.Application;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest(classes = Application.class)
|
||||
@WebAppConfiguration
|
||||
public class QuerydslIntegrationTest {
|
||||
|
||||
final MediaType contentType =
|
||||
new MediaType(MediaType.APPLICATION_JSON.getType(), MediaType.APPLICATION_JSON.getSubtype());
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext webApplicationContext;
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Before
|
||||
public void setupMockMvc() {
|
||||
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequest_whenQueryUserFilteringByCountrySpain_thenGetJohn() throws Exception {
|
||||
mockMvc.perform(get("/users?address.country=Spain")).andExpect(status().isOk()).andExpect(content()
|
||||
.contentType
|
||||
(contentType))
|
||||
.andExpect(jsonPath("$", hasSize(1)))
|
||||
.andExpect(jsonPath("$[0].name", is("John")))
|
||||
.andExpect(jsonPath("$[0].address.address", is("Fake Street 1")))
|
||||
.andExpect(jsonPath("$[0].address.country", is("Spain")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequest_whenQueryUserWithoutFilter_thenGetJohnAndLisa() throws Exception {
|
||||
mockMvc.perform(get("/users")).andExpect(status().isOk()).andExpect(content()
|
||||
.contentType
|
||||
(contentType))
|
||||
.andExpect(jsonPath("$", hasSize(2)))
|
||||
.andExpect(jsonPath("$[0].name", is("John")))
|
||||
.andExpect(jsonPath("$[0].address.address", is("Fake Street 1")))
|
||||
.andExpect(jsonPath("$[0].address.country", is("Spain")))
|
||||
.andExpect(jsonPath("$[1].name", is("Lisa")))
|
||||
.andExpect(jsonPath("$[1].address.address", is("Real Street 1")))
|
||||
.andExpect(jsonPath("$[1].address.country", is("Germany")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:h2:mem:springcloud
|
||||
username: sa
|
||||
password:
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: create-drop
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.H2Dialect
|
||||
Reference in New Issue
Block a user