JAVA-66: New module spring-data-jpa-filtering

This commit is contained in:
sampadawagde 2020-07-19 14:30:43 +05:30
parent 2f81507076
commit 7a86d7de49
30 changed files with 1025 additions and 0 deletions

View File

@ -0,0 +1,19 @@
## Spring Data JPA - Filtering
This module contains articles about filtering data using Spring Data JPA
### Relevant Articles:
- [An Advanced Tagging Implementation with JPA](https://www.baeldung.com/jpa-tagging-advanced)
- [A Simple Tagging Implementation with JPA](https://www.baeldung.com/jpa-tagging)
- [Spring Data JPA and Null Parameters](https://www.baeldung.com/spring-data-jpa-null-parameters)
- [Spring Data JPA Projections](https://www.baeldung.com/spring-data-jpa-projections)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:
"No persistence xml file found in project"
This can be ignored:
- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project"
Or:
- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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-jpa-filtering</artifactId>
<name>spring-data-jpa-filtering</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-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- Test containers only dependencies -->
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>${testcontainers.postgresql.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- Test containers only dependencies -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
<properties>
<start-class>com.baeldung.boot.Application</start-class>
<testcontainers.postgresql.version>1.10.6</testcontainers.postgresql.version>
<postgresql.version>42.2.5</postgresql.version>
<guava.version>21.0</guava.version>
</properties>
</project>

View File

@ -0,0 +1,13 @@
package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,68 @@
package com.baeldung.config;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.inmemory.persistence.dao")
@PropertySource("persistence-student.properties")
@EnableTransactionManagement
public class StudentJpaConfig {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.baeldung.inmemory.persistence.model" });
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
return hibernateProperties;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue
private long id;
private String name;
private String email;
public Customer(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -0,0 +1,10 @@
package com.baeldung.inmemory.persistence.dao;
import com.baeldung.inmemory.persistence.model.ManyStudent;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface ManyStudentRepository extends JpaRepository<ManyStudent, Long> {
List<ManyStudent> findByManyTags_Name(String name);
}

View File

@ -0,0 +1,7 @@
package com.baeldung.inmemory.persistence.dao;
import com.baeldung.inmemory.persistence.model.ManyTag;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ManyTagRepository extends JpaRepository<ManyTag, Long> {
}

View File

@ -0,0 +1,24 @@
package com.baeldung.inmemory.persistence.dao;
import com.baeldung.inmemory.persistence.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface StudentRepository extends JpaRepository<Student, Long> {
@Query("SELECT s FROM Student s JOIN s.tags t WHERE t = LOWER(:tag)")
List<Student> retrieveByTag(@Param("tag") String tag);
@Query("SELECT s FROM Student s JOIN s.tags t WHERE s.name = LOWER(:name) AND t = LOWER(:tag)")
List<Student> retrieveByNameFilterByTag(@Param("name") String name, @Param("tag") String tag);
@Query("SELECT s FROM Student s JOIN s.skillTags t WHERE t.name = LOWER(:tagName) AND t.value > :tagValue")
List<Student> retrieveByNameFilterByMinimumSkillTag(@Param("tagName") String tagName, @Param("tagValue") int tagValue);
@Query("SELECT s FROM Student s JOIN s.kvTags t WHERE t.key = LOWER(:key)")
List<Student> retrieveByKeyTag(@Param("key") String key);
}

View File

@ -0,0 +1,34 @@
package com.baeldung.inmemory.persistence.model;
import javax.persistence.Embeddable;
@Embeddable
public class KVTag {
private String key;
private String value;
public KVTag() {
}
public KVTag(String key, String value) {
super();
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.inmemory.persistence.model;
import javax.persistence.Embeddable;
@Embeddable
public class LocationTag {
private String name;
private int xPos;
private int yPos;
public LocationTag() {
}
public LocationTag(String name, int xPos, int yPos) {
super();
this.name = name;
this.xPos = xPos;
this.yPos = yPos;
}
public String getName() {
return name;
}
public int getxPos() {
return xPos;
}
public void setxPos(int xPos) {
this.xPos = xPos;
}
public int getyPos() {
return yPos;
}
public void setyPos(int yPos) {
this.yPos = yPos;
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.inmemory.persistence.model;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
public class ManyStudent {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "manystudent_manytags", joinColumns = @JoinColumn(name = "manystudent_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "manytag_id", referencedColumnName = "id"))
private Set<ManyTag> manyTags = new HashSet<>();
public ManyStudent() {
}
public ManyStudent(String name) {
this.name = name;
}
public Set<ManyTag> getManyTags() {
return manyTags;
}
public void setManyTags(Set<ManyTag> manyTags) {
this.manyTags.addAll(manyTags);
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.inmemory.persistence.model;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
public class ManyTag {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
@ManyToMany(mappedBy = "manyTags")
private Set<ManyStudent> students = new HashSet<>();
public ManyTag() {
}
public ManyTag(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<ManyStudent> getStudents() {
return students;
}
public void setStudents(Set<ManyStudent> students) {
this.students.addAll(students);
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.inmemory.persistence.model;
import javax.persistence.Embeddable;
@Embeddable
public class SkillTag {
private String name;
private int value;
public SkillTag() {
}
public SkillTag(String name, int value) {
super();
this.name = name;
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,74 @@
package com.baeldung.inmemory.persistence.model;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Student {
@Id
private long id;
private String name;
@ElementCollection
private List<String> tags = new ArrayList<>();
@ElementCollection
private List<SkillTag> skillTags = new ArrayList<>();
@ElementCollection
private List<KVTag> kvTags = new ArrayList<>();
public Student() {
}
public Student(long id, String name) {
super();
this.id = id;
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 List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags.addAll(tags);
}
public List<SkillTag> getSkillTags() {
return skillTags;
}
public void setSkillTags(List<SkillTag> skillTags) {
this.skillTags.addAll(skillTags);
}
public List<KVTag> getKVTags() {
return this.kvTags;
}
public void setKVTags(List<KVTag> kvTags) {
this.kvTags.addAll(kvTags);
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.projection.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Address {
@Id
private Long id;
@OneToOne
private Person person;
private String state;
private String city;
private String street;
private String zipCode;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.projection.model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class Person {
@Id
private Long id;
private String firstName;
private String lastName;
@OneToOne(mappedBy = "person")
private Address address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}

View File

@ -0,0 +1,11 @@
package com.baeldung.projection.repository;
import com.baeldung.projection.view.AddressView;
import com.baeldung.projection.model.Address;
import org.springframework.data.repository.Repository;
import java.util.List;
public interface AddressRepository extends Repository<Address, Long> {
List<AddressView> getAddressByState(String state);
}

View File

@ -0,0 +1,14 @@
package com.baeldung.projection.repository;
import com.baeldung.projection.model.Person;
import com.baeldung.projection.view.PersonDto;
import com.baeldung.projection.view.PersonView;
import org.springframework.data.repository.Repository;
public interface PersonRepository extends Repository<Person, Long> {
PersonView findByLastName(String lastName);
PersonDto findByFirstName(String firstName);
<T> T findByLastName(String lastName, Class<T> type);
}

View File

@ -0,0 +1,7 @@
package com.baeldung.projection.view;
public interface AddressView {
String getZipCode();
PersonView getPerson();
}

View File

@ -0,0 +1,34 @@
package com.baeldung.projection.view;
import java.util.Objects;
public class PersonDto {
private final String firstName;
private final String lastName;
public PersonDto(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonDto personDto = (PersonDto) o;
return Objects.equals(firstName, personDto.firstName) && Objects.equals(lastName, personDto.lastName);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.projection.view;
import org.springframework.beans.factory.annotation.Value;
public interface PersonView {
String getFirstName();
String getLastName();
@Value("#{target.firstName + ' ' + target.lastName}")
String getFullName();
}

View File

@ -0,0 +1,19 @@
package com.baeldung.repository;
import com.baeldung.entity.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface CustomerRepository extends JpaRepository<Customer, Long> {
List<Customer> findByName(String name);
List<Customer> findByNameAndEmail(String name, String email);
@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null or c.email = :email)")
List<Customer> findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);
}

View File

@ -0,0 +1,11 @@
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myDb
jdbc.user=tutorialuser
jdbc.pass=tutorialpass
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create-drop
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false

View File

@ -0,0 +1,83 @@
package com.baeldung.persistence.repository;
import com.baeldung.config.StudentJpaConfig;
import com.baeldung.inmemory.persistence.dao.ManyStudentRepository;
import com.baeldung.inmemory.persistence.dao.ManyTagRepository;
import com.baeldung.inmemory.persistence.dao.StudentRepository;
import com.baeldung.inmemory.persistence.model.ManyStudent;
import com.baeldung.inmemory.persistence.model.ManyTag;
import com.baeldung.inmemory.persistence.model.SkillTag;
import com.baeldung.inmemory.persistence.model.Student;
import com.baeldung.inmemory.persistence.model.KVTag;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { StudentJpaConfig.class }, loader = AnnotationConfigContextLoader.class)
@Transactional
@DirtiesContext
public class AdvancedTaggingIntegrationTest {
@Resource
private StudentRepository studentRepository;
@Resource
private ManyStudentRepository manyStudentRepository;
@Resource
private ManyTagRepository manyTagRepository;
@Test
public void givenStudentWithSkillTags_whenSave_thenGetByNameAndSkillTag() {
Student student = new Student(1, "Will");
SkillTag skill1 = new SkillTag("java", 5);
student.setSkillTags(Arrays.asList(skill1));
studentRepository.save(student);
Student student2 = new Student(2, "Joe");
SkillTag skill2 = new SkillTag("java", 1);
student2.setSkillTags(Arrays.asList(skill2));
studentRepository.save(student2);
List<Student> students = studentRepository.retrieveByNameFilterByMinimumSkillTag("java", 3);
assertEquals("size incorrect", 1, students.size());
}
@Test
public void givenStudentWithKVTags_whenSave_thenGetByTagOk() {
Student student = new Student(0, "John");
student.setKVTags(Arrays.asList(new KVTag("department", "computer science")));
studentRepository.save(student);
Student student2 = new Student(1, "James");
student2.setKVTags(Arrays.asList(new KVTag("department", "humanities")));
studentRepository.save(student2);
List<Student> students = studentRepository.retrieveByKeyTag("department");
assertEquals("size incorrect", 2, students.size());
}
@Test
public void givenStudentWithManyTags_whenSave_theyGetByTagOk() {
ManyTag tag = new ManyTag("full time");
manyTagRepository.save(tag);
ManyStudent student = new ManyStudent("John");
student.setManyTags(Collections.singleton(tag));
manyStudentRepository.save(student);
List<ManyStudent> students = manyStudentRepository.findByManyTags_Name("full time");
assertEquals("size incorrect", 1, students.size());
}
}

View File

@ -0,0 +1,84 @@
package com.baeldung.persistence.repository;
import com.baeldung.config.StudentJpaConfig;
import com.baeldung.inmemory.persistence.dao.StudentRepository;
import com.baeldung.inmemory.persistence.model.Student;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { StudentJpaConfig.class }, loader = AnnotationConfigContextLoader.class)
@Transactional
@DirtiesContext
public class InMemoryDBIntegrationTest {
@Resource
private StudentRepository studentRepository;
private static final long ID = 1;
private static final String NAME = "john";
@Test
public void givenStudent_whenSave_thenGetOk() {
Student student = new Student(ID, NAME);
studentRepository.save(student);
Student student2 = studentRepository.findById(ID).get();
assertEquals("name incorrect", NAME, student2.getName());
}
@Test
public void givenStudentWithTags_whenSave_thenGetByTagOk() {
Student student = new Student(ID, NAME);
student.setTags(Arrays.asList("full time", "computer science"));
studentRepository.save(student);
Student student2 = studentRepository.retrieveByTag("full time").get(0);
assertEquals("name incorrect", NAME, student2.getName());
}
@Test
public void givenMultipleStudentsWithTags_whenSave_thenGetByTagReturnsCorrectCount() {
Student student = new Student(0, "Larry");
student.setTags(Arrays.asList("full time", "computer science"));
studentRepository.save(student);
Student student2 = new Student(1, "Curly");
student2.setTags(Arrays.asList("part time", "rocket science"));
studentRepository.save(student2);
Student student3 = new Student(2, "Moe");
student3.setTags(Arrays.asList("full time", "philosophy"));
studentRepository.save(student3);
Student student4 = new Student(3, "Shemp");
student4.setTags(Arrays.asList("part time", "mathematics"));
studentRepository.save(student4);
List<Student> students = studentRepository.retrieveByTag("full time");
assertEquals("size incorrect", 2, students.size());
}
@Test
public void givenStudentWithTags_whenSave_thenGetByNameAndTagOk() {
Student student = new Student(ID, NAME);
student.setTags(Arrays.asList("full time", "computer science"));
studentRepository.save(student);
Student student2 = studentRepository.retrieveByNameFilterByTag("John", "full time").get(0);
assertEquals("name incorrect", NAME, student2.getName());
}
}

View File

@ -0,0 +1,63 @@
package com.baeldung.projection;
import com.baeldung.projection.model.Person;
import com.baeldung.projection.repository.AddressRepository;
import com.baeldung.projection.repository.PersonRepository;
import com.baeldung.projection.view.AddressView;
import com.baeldung.projection.view.PersonDto;
import com.baeldung.projection.view.PersonView;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
@DataJpaTest
@RunWith(SpringRunner.class)
@Sql(scripts = "/projection-insert-data.sql")
@Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD)
public class JpaProjectionIntegrationTest {
@Autowired
private AddressRepository addressRepository;
@Autowired
private PersonRepository personRepository;
@Test
public void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned() {
AddressView addressView = addressRepository.getAddressByState("CA").get(0);
assertThat(addressView.getZipCode()).isEqualTo("90001");
PersonView personView = addressView.getPerson();
assertThat(personView.getFirstName()).isEqualTo("John");
assertThat(personView.getLastName()).isEqualTo("Doe");
}
@Test
public void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned() {
PersonView personView = personRepository.findByLastName("Doe");
assertThat(personView.getFullName()).isEqualTo("John Doe");
}
@Test
public void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned() {
PersonDto personDto = personRepository.findByFirstName("John");
assertThat(personDto.getFirstName()).isEqualTo("John");
assertThat(personDto.getLastName()).isEqualTo("Doe");
}
@Test
public void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned() {
Person person = personRepository.findByLastName("Doe", Person.class);
PersonView personView = personRepository.findByLastName("Doe", PersonView.class);
PersonDto personDto = personRepository.findByLastName("Doe", PersonDto.class);
assertThat(person.getFirstName()).isEqualTo("John");
assertThat(personView.getFirstName()).isEqualTo("John");
assertThat(personDto.getFirstName()).isEqualTo("John");
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.repository;
import com.baeldung.entity.Customer;
import org.junit.After;
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.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import static org.junit.Assert.assertEquals;
@DataJpaTest
@RunWith(SpringRunner.class)
public class CustomerRepositoryIntegrationTest {
@PersistenceContext
private EntityManager entityManager;
@Autowired
private CustomerRepository repository;
@Before
public void before() {
entityManager.persist(new Customer("A", "A@example.com"));
entityManager.persist(new Customer("D", null));
entityManager.persist(new Customer("D", "D@example.com"));
}
@Test
public void givenQueryMethod_whenEmailIsNull_thenFoundByNullEmail() {
List<Customer> customers = repository.findByNameAndEmail("D", null);
assertEquals(1, customers.size());
Customer actual = customers.get(0);
assertEquals(null, actual.getEmail());
assertEquals("D", actual.getName());
}
@Test
public void givenQueryMethod_whenEmailIsAbsent_thenIgnoreEmail() {
List<Customer> customers = repository.findByName("D");
assertEquals(2, customers.size());
}
@Test
public void givenQueryAnnotation_whenEmailIsNull_thenIgnoreEmail() {
List<Customer> customers = repository.findCustomerByNameAndEmail("D", null);
assertEquals(2, customers.size());
}
@After
public void cleanUp() {
repository.deleteAll();
}
}

View File

@ -0,0 +1,9 @@
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=create
hibernate.cache.use_second_level_cache=false
hibernate.cache.use_query_cache=false

View File

@ -0,0 +1,2 @@
DELETE FROM address;
DELETE FROM person;

View File

@ -0,0 +1,2 @@
INSERT INTO person(id,first_name,last_name) VALUES (1,'John','Doe');
INSERT INTO address(id,person_id,state,city,street,zip_code) VALUES (1,1,'CA', 'Los Angeles', 'Standford Ave', '90001');