JAVA-66: New module spring-data-jpa-filtering
This commit is contained in:
parent
2f81507076
commit
7a86d7de49
|
@ -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
|
||||
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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> {
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.projection.view;
|
||||
|
||||
public interface AddressView {
|
||||
String getZipCode();
|
||||
|
||||
PersonView getPerson();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,2 @@
|
|||
DELETE FROM address;
|
||||
DELETE FROM person;
|
|
@ -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');
|
Loading…
Reference in New Issue