diff --git a/persistence-modules/spring-data-jpa-query/README.md b/persistence-modules/spring-data-jpa-query/README.md new file mode 100644 index 0000000000..bfff3c0ef3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/README.md @@ -0,0 +1,22 @@ +## Spring Data JPA - Query + +This module contains articles about querying data using Spring Data JPA + +### Relevant Articles: +- [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) +- [The Exists Query in Spring Data](https://www.baeldung.com/spring-data-exists-query) +- [Customizing the Result of JPA Queries with Aggregation Functions](https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions) +- [Limiting Query Results with JPA and Spring Data JPA](https://www.baeldung.com/jpa-limit-query-results) +- [Sorting Query Results with Spring Data](https://www.baeldung.com/spring-data-sorting) +- [Spring Data JPA Query by Example](https://www.baeldung.com/spring-data-query-by-example) +- [JPA Join Types](https://www.baeldung.com/jpa-join-types) +- [Spring Data JPA and Named Entity Graphs](https://www.baeldung.com/spring-data-jpa-named-entity-graphs) + +### 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 diff --git a/persistence-modules/spring-data-jpa-query/pom.xml b/persistence-modules/spring-data-jpa-query/pom.xml new file mode 100644 index 0000000000..71498143c3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + spring-data-jpa-query + spring-data-jpa-query + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + com.h2database + h2 + + + + net.ttddyy + datasource-proxy + ${datasource-proxy.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.springframework + spring-oxm + + + + + 1.4.1 + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/Application.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..3ea3d113da --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/Application.java @@ -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); + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java new file mode 100644 index 0000000000..26c2373cbe --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Comment.java @@ -0,0 +1,85 @@ +package com.baeldung.aggregation.model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import java.util.Objects; + +@Entity +public class Comment { + @Id + private Integer id; + private Integer year; + private boolean approved; + private String content; + @ManyToOne + private Post post; + + public Comment() { + } + + public Comment(int id, int year, boolean approved, String content, Post post) { + this.id = id; + this.year = year; + this.approved = approved; + this.content = content; + this.post = post; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getYear() { + return year; + } + + public void setYear(Integer year) { + this.year = year; + } + + public boolean isApproved() { + return approved; + } + + public void setApproved(boolean approved) { + this.approved = approved; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Post getPost() { + return post; + } + + public void setPost(Post post) { + this.post = post; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Comment)) { + return false; + } + Comment comment = (Comment) o; + return getId().equals(comment.getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getId()); + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java new file mode 100644 index 0000000000..f396e080ae --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/Post.java @@ -0,0 +1,75 @@ +package com.baeldung.aggregation.model; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.List; +import java.util.Objects; + +@Entity +public class Post { + @Id + private Integer id; + private String title; + private String content; + @OneToMany(mappedBy = "post") + private List comments; + + public Post() { + } + + public Post(Integer id, String title, String content) { + this.id = id; + this.title = title; + this.content = content; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public List getComments() { + return comments; + } + + public void setComments(List comments) { + this.comments = comments; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Post)) { + return false; + } + Post post = (Post) o; + return getId().equals(post.getId()); + } + + @Override + public int hashCode() { + return Objects.hash(getId()); + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java new file mode 100644 index 0000000000..510b52a47c --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/CommentCount.java @@ -0,0 +1,27 @@ +package com.baeldung.aggregation.model.custom; + +public class CommentCount { + private Integer year; + private Long total; + + public CommentCount(Integer year, Long total) { + this.year = year; + this.total = total; + } + + public Integer getYear() { + return year; + } + + public void setYear(Integer year) { + this.year = year; + } + + public Long getTotal() { + return total; + } + + public void setTotal(Long total) { + this.total = total; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java new file mode 100644 index 0000000000..acb25cfd49 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/model/custom/ICommentCount.java @@ -0,0 +1,8 @@ +package com.baeldung.aggregation.model.custom; + +public interface ICommentCount { + + Integer getYearComment(); + + Long getTotalComment(); +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java new file mode 100644 index 0000000000..89e9345e94 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/aggregation/repository/CommentRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.aggregation.repository; + +import com.baeldung.aggregation.model.Comment; +import com.baeldung.aggregation.model.custom.CommentCount; +import com.baeldung.aggregation.model.custom.ICommentCount; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface CommentRepository extends JpaRepository { + + @Query("SELECT c.year, COUNT(c.year) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") + List countTotalCommentsByYear(); + + @Query("SELECT new com.baeldung.aggregation.model.custom.CommentCount(c.year, COUNT(c.year)) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") + List countTotalCommentsByYearClass(); + + @Query("SELECT c.year AS yearComment, COUNT(c.year) AS totalComment FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC") + List countTotalCommentsByYearInterface(); + + @Query(value = "SELECT c.year AS yearComment, COUNT(c.*) AS totalComment FROM comment AS c GROUP BY c.year ORDER BY c.year DESC", nativeQuery = true) + List countTotalCommentsByYearNative(); + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/daos/ArticleRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/daos/ArticleRepository.java new file mode 100644 index 0000000000..73397ad42e --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/daos/ArticleRepository.java @@ -0,0 +1,23 @@ +package com.baeldung.boot.daos; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import com.baeldung.boot.domain.Article; + +import java.util.Date; +import java.util.List; + +public interface ArticleRepository extends JpaRepository { + + List
findAllByPublicationDate(Date publicationDate); + + List
findAllByPublicationTimeBetween(Date publicationTimeStart, + Date publicationTimeEnd); + + @Query("select a from Article a where a.creationDateTime <= :creationDateTime") + List
findAllWithCreationDateTimeBefore( + @Param("creationDateTime") Date creationDateTime); + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/domain/Article.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/domain/Article.java new file mode 100644 index 0000000000..de4dbed1a0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/domain/Article.java @@ -0,0 +1,23 @@ +package com.baeldung.boot.domain; + +import javax.persistence.*; +import java.util.Date; + +@Entity +public class Article { + + @Id + @GeneratedValue + private Integer id; + @Temporal(TemporalType.DATE) + private Date publicationDate; + @Temporal(TemporalType.TIME) + private Date publicationTime; + @Temporal(TemporalType.TIMESTAMP) + private Date creationDateTime; + + public Integer getId() { + return id; + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java new file mode 100644 index 0000000000..7152286c83 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/CustomPassengerRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.passenger; + +import java.util.List; + +interface CustomPassengerRepository { + + List findOrderedBySeatNumberLimitedTo(int limit); +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/Passenger.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/Passenger.java new file mode 100644 index 0000000000..c75107a783 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/Passenger.java @@ -0,0 +1,82 @@ +package com.baeldung.boot.passenger; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +class Passenger { + + @Id + @GeneratedValue + @Column(nullable = false) + private Long id; + + @Basic(optional = false) + @Column(nullable = false) + private String firstName; + + @Basic(optional = false) + @Column(nullable = false) + private String lastName; + + @Basic(optional = false) + @Column(nullable = false) + private Integer seatNumber; + + private Passenger(String firstName, String lastName, Integer seatNumber) { + this.firstName = firstName; + this.lastName = lastName; + this.seatNumber = seatNumber; + } + + static Passenger from(String firstName, String lastName, Integer seatNumber) { + return new Passenger(firstName, lastName, seatNumber); + } + + @Override + public boolean equals(Object object) { + if (this == object) + return true; + if (object == null || getClass() != object.getClass()) + return false; + Passenger passenger = (Passenger) object; + return getSeatNumber() == passenger.getSeatNumber() && Objects.equals(getFirstName(), passenger.getFirstName()) + && Objects.equals(getLastName(), passenger.getLastName()); + } + + @Override + public int hashCode() { + return Objects.hash(getFirstName(), getLastName(), getSeatNumber()); + } + + @Override + public String toString() { + final StringBuilder toStringBuilder = new StringBuilder(getClass().getSimpleName()); + toStringBuilder.append("{ id=").append(id); + toStringBuilder.append(", firstName='").append(firstName).append('\''); + toStringBuilder.append(", lastName='").append(lastName).append('\''); + toStringBuilder.append(", seatNumber=").append(seatNumber); + toStringBuilder.append('}'); + return toStringBuilder.toString(); + } + + Long getId() { + return id; + } + + String getFirstName() { + return firstName; + } + + String getLastName() { + return lastName; + } + + Integer getSeatNumber() { + return seatNumber; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepository.java new file mode 100644 index 0000000000..14d5403cb5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepository.java @@ -0,0 +1,22 @@ +package com.baeldung.boot.passenger; + +import java.util.List; + +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.repository.JpaRepository; + +interface PassengerRepository extends JpaRepository, CustomPassengerRepository { + + Passenger findFirstByOrderBySeatNumberAsc(); + + Passenger findTopByOrderBySeatNumberAsc(); + + List findByOrderBySeatNumberAsc(); + + List findByFirstNameIgnoreCase(String firstName); + + List findByLastNameOrderBySeatNumberAsc(String lastName); + + List findByLastName(String lastName, Sort sort); + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java new file mode 100644 index 0000000000..508c669066 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/boot/passenger/PassengerRepositoryImpl.java @@ -0,0 +1,20 @@ +package com.baeldung.boot.passenger; + +import org.springframework.stereotype.Repository; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; + +@Repository +class PassengerRepositoryImpl implements CustomPassengerRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findOrderedBySeatNumberLimitedTo(int limit) { + return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber", + Passenger.class).setMaxResults(limit).getResultList(); + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Characteristic.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Characteristic.java new file mode 100644 index 0000000000..ae20375572 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Characteristic.java @@ -0,0 +1,43 @@ +package com.baeldung.entitygraph.model; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Characteristic { + + @Id + private Long id; + private String type; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn + private Item item; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Item getItem() { + return item; + } + + public void setItem(Item item) { + this.item = item; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Item.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Item.java new file mode 100644 index 0000000000..e90a22ef62 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/model/Item.java @@ -0,0 +1,48 @@ +package com.baeldung.entitygraph.model; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.OneToMany; + +@Entity +@NamedEntityGraph(name = "Item.characteristics", + attributeNodes = @NamedAttributeNode("characteristics") +) +public class Item { + + @Id + private Long id; + private String name; + + @OneToMany(mappedBy = "item") + private List characteristics = new ArrayList<>(); + + 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 getCharacteristics() { + return characteristics; + } + + public void setCharacteristics(List characteristics) { + this.characteristics = characteristics; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java new file mode 100644 index 0000000000..9f923ab241 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/CharacteristicsRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.entitygraph.repository; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.entitygraph.model.Characteristic; + +public interface CharacteristicsRepository extends JpaRepository { + + @EntityGraph(attributePaths = {"item"}) + Characteristic findByType(String type); + +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java new file mode 100644 index 0000000000..b2a5f223b3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/entitygraph/repository/ItemRepository.java @@ -0,0 +1,13 @@ +package com.baeldung.entitygraph.repository; + +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; +import org.springframework.data.jpa.repository.JpaRepository; + +import com.baeldung.entitygraph.model.Item; + +public interface ItemRepository extends JpaRepository { + + @EntityGraph(value = "Item.characteristics", type = EntityGraphType.FETCH) + Item findByName(String name); +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/Car.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/Car.java new file mode 100644 index 0000000000..bf09caf6ff --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/Car.java @@ -0,0 +1,48 @@ +package com.baeldung.exists; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author paullatzelsperger + * @since 2019-03-20 + */ +@Entity +public class Car { + + @Id + @GeneratedValue + private int id; + private Integer power; + private String model; + + Car() { + + } + + public Car(int power, String model) { + this.power = power; + this.model = model; + } + + public Integer getPower() { + return power; + } + + public void setPower(Integer power) { + this.power = power; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public int getId() { + return id; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/CarRepository.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/CarRepository.java new file mode 100644 index 0000000000..a54f19f4cd --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/exists/CarRepository.java @@ -0,0 +1,24 @@ +package com.baeldung.exists; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +/** + * @author paullatzelsperger + * @since 2019-03-20 + */ +@Repository +public interface CarRepository extends JpaRepository { + + boolean existsCarByPower(int power); + + boolean existsCarByModel(String model); + + @Query("select case when count(c)> 0 then true else false end from Car c where c.model = :model") + boolean existsCarExactCustomQuery(@Param("model") String model); + + @Query("select case when count(c)> 0 then true else false end from Car c where lower(c.model) like lower(:model)") + boolean existsCarLikeCustomQuery(@Param("model") String model); +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Department.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Department.java new file mode 100644 index 0000000000..439f7532f5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Department.java @@ -0,0 +1,45 @@ +package com.baeldung.joins.model; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity +public class Department { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + @OneToMany(mappedBy = "department") + private List employees; + + 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 getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Employee.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Employee.java new file mode 100644 index 0000000000..277274e61c --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Employee.java @@ -0,0 +1,69 @@ +package com.baeldung.joins.model; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "joins_employee") +public class Employee { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + private int age; + + @ManyToOne + private Department department; + + @OneToMany(mappedBy = "employee") + private List phones; + + 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 int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public Department getDepartment() { + return department; + } + + public void setDepartment(Department department) { + this.department = department; + } + + public List getPhones() { + return phones; + } + + public void setPhones(List phones) { + this.phones = phones; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Phone.java b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Phone.java new file mode 100644 index 0000000000..41382915b1 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/java/com/baeldung/joins/model/Phone.java @@ -0,0 +1,44 @@ +package com.baeldung.joins.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Phone { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String number; + + @ManyToOne + private Employee employee; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } + + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/apple-fruit-data.xml b/persistence-modules/spring-data-jpa-query/src/main/resources/apple-fruit-data.xml new file mode 100644 index 0000000000..d87ae28f1e --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/apple-fruit-data.xml @@ -0,0 +1,7 @@ + + + + 1 + apple + red + diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/application-joins.properties b/persistence-modules/spring-data-jpa-query/src/main/resources/application-joins.properties new file mode 100644 index 0000000000..fe2270293b --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/application-joins.properties @@ -0,0 +1 @@ +spring.datasource.data=classpath:db/import_joins.sql diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties b/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties new file mode 100644 index 0000000000..72fc330767 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.jpa.show-sql=true \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/db/import_joins.sql b/persistence-modules/spring-data-jpa-query/src/main/resources/db/import_joins.sql new file mode 100644 index 0000000000..e4772d6ff2 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/db/import_joins.sql @@ -0,0 +1,13 @@ +INSERT INTO department (id, name) VALUES (1, 'Infra'); +INSERT INTO department (id, name) VALUES (2, 'Accounting'); +INSERT INTO department (id, name) VALUES (3, 'Management'); + +INSERT INTO joins_employee (id, name, age, department_id) VALUES (1, 'Baeldung', '35', 1); +INSERT INTO joins_employee (id, name, age, department_id) VALUES (2, 'John', '35', 2); +INSERT INTO joins_employee (id, name, age, department_id) VALUES (3, 'Jane', '35', 2); + +INSERT INTO phone (id, number, employee_id) VALUES (1, '111', 1); +INSERT INTO phone (id, number, employee_id) VALUES (2, '222', 1); +INSERT INTO phone (id, number, employee_id) VALUES (3, '333', 1); + +COMMIT; diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/fruit-data.json b/persistence-modules/spring-data-jpa-query/src/main/resources/fruit-data.json new file mode 100644 index 0000000000..6dc44e2586 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/fruit-data.json @@ -0,0 +1,14 @@ +[ + { + "_class": "com.baeldung.entity.Fruit", + "name": "apple", + "color": "red", + "id": 1 + }, + { + "_class": "com.baeldung.entity.Fruit", + "name": "guava", + "color": "green", + "id": 2 + } +] \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/guava-fruit-data.xml b/persistence-modules/spring-data-jpa-query/src/main/resources/guava-fruit-data.xml new file mode 100644 index 0000000000..ffd75bb4bb --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/guava-fruit-data.xml @@ -0,0 +1,7 @@ + + + + 2 + guava + green + diff --git a/persistence-modules/spring-data-jpa-query/src/main/resources/import_entities.sql b/persistence-modules/spring-data-jpa-query/src/main/resources/import_entities.sql new file mode 100644 index 0000000000..4fe18bf4aa --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/main/resources/import_entities.sql @@ -0,0 +1,3 @@ +insert into Article(id, publication_date, publication_time, creation_date_time) values(1, TO_DATE('01/01/2018', 'DD/MM/YYYY'), TO_DATE('15:00', 'HH24:MI'), TO_DATE('31/12/2017 07:30', 'DD/MM/YYYY HH24:MI')); +insert into Article(id, publication_date, publication_time, creation_date_time) values(2, TO_DATE('01/01/2018', 'DD/MM/YYYY'), TO_DATE('15:30', 'HH24:MI'), TO_DATE('15/12/2017 08:00', 'DD/MM/YYYY HH24:MI')); +insert into Article(id, publication_date, publication_time, creation_date_time) values(3, TO_DATE('15/12/2017', 'DD/MM/YYYY'), TO_DATE('16:00', 'HH24:MI'), TO_DATE('01/12/2017 13:45', 'DD/MM/YYYY HH24:MI')); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java new file mode 100644 index 0000000000..779ade7a3f --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/aggregation/SpringDataAggregateIntegrationTest.java @@ -0,0 +1,107 @@ +package com.baeldung.aggregation; + +import com.baeldung.aggregation.model.custom.CommentCount; +import com.baeldung.aggregation.model.custom.ICommentCount; +import com.baeldung.aggregation.repository.CommentRepository; +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 java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +@RunWith(SpringRunner.class) +@DataJpaTest + +@Sql(scripts = "/test-aggregation-data.sql") +public class SpringDataAggregateIntegrationTest { + + @Autowired + private CommentRepository commentRepository; + + @Test + public void whenQueryWithAggregation_thenReturnResult() { + List commentCountsByYear = commentRepository.countTotalCommentsByYear(); + + Object[] countYear2019 = commentCountsByYear.get(0); + + assertThat(countYear2019[0], is(Integer.valueOf(2019))); + assertThat(countYear2019[1], is(1l)); + + Object[] countYear2018 = commentCountsByYear.get(1); + + assertThat(countYear2018[0], is(Integer.valueOf(2018))); + assertThat(countYear2018[1], is(2l)); + + Object[] countYear2017 = commentCountsByYear.get(2); + + assertThat(countYear2017[0], is(Integer.valueOf(2017))); + assertThat(countYear2017[1], is(1l)); + } + + @Test + public void whenQueryWithAggregation_thenReturnCustomResult() { + List commentCountsByYear = commentRepository.countTotalCommentsByYearClass(); + + CommentCount countYear2019 = commentCountsByYear.get(0); + + assertThat(countYear2019.getYear(), is(Integer.valueOf(2019))); + assertThat(countYear2019.getTotal(), is(1l)); + + CommentCount countYear2018 = commentCountsByYear.get(1); + + assertThat(countYear2018.getYear(), is(Integer.valueOf(2018))); + assertThat(countYear2018.getTotal(), is(2l)); + + CommentCount countYear2017 = commentCountsByYear.get(2); + + assertThat(countYear2017.getYear(), is(Integer.valueOf(2017))); + assertThat(countYear2017.getTotal(), is(1l)); + } + + @Test + public void whenQueryWithAggregation_thenReturnInterfaceResult() { + List commentCountsByYear = commentRepository.countTotalCommentsByYearInterface(); + + ICommentCount countYear2019 = commentCountsByYear.get(0); + + assertThat(countYear2019.getYearComment(), is(Integer.valueOf(2019))); + assertThat(countYear2019.getTotalComment(), is(1l)); + + ICommentCount countYear2018 = commentCountsByYear.get(1); + + assertThat(countYear2018.getYearComment(), is(Integer.valueOf(2018))); + assertThat(countYear2018.getTotalComment(), is(2l)); + + ICommentCount countYear2017 = commentCountsByYear.get(2); + + assertThat(countYear2017.getYearComment(), is(Integer.valueOf(2017))); + assertThat(countYear2017.getTotalComment(), is(1l)); + } + + @Test + public void whenNativeQueryWithAggregation_thenReturnInterfaceResult() { + List commentCountsByYear = commentRepository.countTotalCommentsByYearNative(); + + ICommentCount countYear2019 = commentCountsByYear.get(0); + + assertThat(countYear2019.getYearComment(), is(Integer.valueOf(2019))); + assertThat(countYear2019.getTotalComment(), is(1l)); + + ICommentCount countYear2018 = commentCountsByYear.get(1); + + assertThat(countYear2018.getYearComment(), is(Integer.valueOf(2018))); + assertThat(countYear2018.getTotalComment(), is(2l)); + + ICommentCount countYear2017 = commentCountsByYear.get(2); + + assertThat(countYear2017.getYearComment(), is(Integer.valueOf(2017))); + assertThat(countYear2017.getTotalComment(), is(1l)); + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java new file mode 100644 index 0000000000..20fc3cbeaf --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/daos/ArticleRepositoryIntegrationTest.java @@ -0,0 +1,67 @@ +package com.baeldung.boot.daos; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.List; + +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 com.baeldung.boot.domain.Article; + +@RunWith(SpringRunner.class) +@DataJpaTest(properties="spring.datasource.data=classpath:import_entities.sql") +public class ArticleRepositoryIntegrationTest { + + @Autowired + private ArticleRepository repository; + + @Test + public void givenImportedArticlesWhenFindAllByPublicationDateThenArticles1And2Returned() + throws Exception { + List
result = repository.findAllByPublicationDate( + new SimpleDateFormat("yyyy-MM-dd").parse("2018-01-01") + ); + + assertEquals(2, result.size()); + assertTrue(result.stream() + .map(Article::getId) + .allMatch(id -> Arrays.asList(1, 2).contains(id)) + ); + } + + @Test + public void givenImportedArticlesWhenFindAllByPublicationTimeBetweenThenArticles2And3Returned() + throws Exception { + List
result = repository.findAllByPublicationTimeBetween( + new SimpleDateFormat("HH:mm").parse("15:15"), + new SimpleDateFormat("HH:mm").parse("16:30") + ); + + assertEquals(2, result.size()); + assertTrue(result.stream() + .map(Article::getId) + .allMatch(id -> Arrays.asList(2, 3).contains(id)) + ); + } + + @Test + public void givenImportedArticlesWhenFindAllWithCreationDateTimeBeforeThenArticles2And3Returned() throws Exception { + List
result = repository.findAllWithCreationDateTimeBefore( + new SimpleDateFormat("yyyy-MM-dd HH:mm").parse("2017-12-15 10:00") + ); + + assertEquals(2, result.size()); + assertTrue(result.stream() + .map(Article::getId) + .allMatch(id -> Arrays.asList(2, 3).contains(id)) + ); + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java new file mode 100644 index 0000000000..f082350019 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/boot/passenger/PassengerRepositoryIntegrationTest.java @@ -0,0 +1,190 @@ +package com.baeldung.boot.passenger; + +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.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.boot.passenger.Passenger; +import com.baeldung.boot.passenger.PassengerRepository; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.util.List; +import java.util.Optional; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +@DataJpaTest +@RunWith(SpringRunner.class) +public class PassengerRepositoryIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + @Autowired + private PassengerRepository repository; + + @Before + public void before() { + entityManager.persist(Passenger.from("Jill", "Smith", 50)); + entityManager.persist(Passenger.from("Eve", "Jackson", 95)); + entityManager.persist(Passenger.from("Fred", "Bloggs", 22)); + entityManager.persist(Passenger.from("Ricki", "Bobbie", 36)); + entityManager.persist(Passenger.from("Siya", "Kolisi", 85)); + } + + @Test + public void givenSeveralPassengersWhenOrderedBySeatNumberLimitedToThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + List passengers = repository.findOrderedBySeatNumberLimitedTo(1); + + assertEquals(1, passengers.size()); + + Passenger actual = passengers.get(0); + assertEquals(expected, actual); + } + + @Test + public void givenSeveralPassengersWhenFindFirstByOrderBySeatNumberAscThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + Passenger actual = repository.findFirstByOrderBySeatNumberAsc(); + + assertEquals(expected, actual); + } + + @Test + public void givenSeveralPassengersWhenFindPageSortedByThenThePassengerInTheFirstFilledSeatIsReturned() { + Passenger expected = Passenger.from("Fred", "Bloggs", 22); + + Page page = repository.findAll(PageRequest.of(0, 1, + Sort.by(Sort.Direction.ASC, "seatNumber"))); + + assertEquals(1, page.getContent().size()); + + Passenger actual = page.getContent().get(0); + assertEquals(expected, actual); + } + + @Test + public void givenPassengers_whenOrderedBySeatNumberAsc_thenCorrectOrder() { + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + + List passengers = repository.findByOrderBySeatNumberAsc(); + + assertThat(passengers, contains(fred, ricki, jill, siya, eve)); + } + + @Test + public void givenPassengers_whenFindAllWithSortBySeatNumberAsc_thenCorrectOrder() { + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + + List passengers = repository.findAll(Sort.by(Sort.Direction.ASC, "seatNumber")); + + assertThat(passengers, contains(fred, ricki, jill, siya, eve)); + } + + @Test + public void givenPassengers_whenFindByExampleDefaultMatcher_thenExpectedReturned() { + Example example = Example.of(Passenger.from("Fred", "Bloggs", null)); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); + } + + @Test + public void givenPassengers_whenFindByExampleCaseInsensitiveMatcher_thenExpectedReturned() { + ExampleMatcher caseInsensitiveExampleMatcher = ExampleMatcher.matchingAll().withIgnoreCase(); + Example example = Example.of(Passenger.from("fred", "bloggs", null), + caseInsensitiveExampleMatcher); + + Optional actual = repository.findOne(example); + + assertTrue(actual.isPresent()); + assertEquals(Passenger.from("Fred", "Bloggs", 22), actual.get()); + } + + @Test + public void givenPassengers_whenFindByExampleCustomMatcher_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + ExampleMatcher customExampleMatcher = ExampleMatcher.matchingAny().withMatcher("firstName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()).withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.contains().ignoreCase()); + + Example example = Example.of(Passenger.from("e", "s", null), + customExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(jill, eve, fred, siya)); + assertThat(passengers, not(contains(ricki))); + } + + @Test + public void givenPassengers_whenFindByIgnoringMatcher_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + ExampleMatcher ignoringExampleMatcher = ExampleMatcher.matchingAny().withMatcher("lastName", + ExampleMatcher.GenericPropertyMatchers.startsWith().ignoreCase()).withIgnorePaths("firstName", "seatNumber"); + + Example example = Example.of(Passenger.from(null, "b", null), + ignoringExampleMatcher); + + List passengers = repository.findAll(example); + + assertThat(passengers, contains(fred, ricki)); + assertThat(passengers, not(contains(jill))); + assertThat(passengers, not(contains(eve))); + assertThat(passengers, not(contains(siya))); + } + + @Test + public void givenPassengers_whenMatchingIgnoreCase_thenExpectedReturned() { + Passenger jill = Passenger.from("Jill", "Smith", 50); + Passenger eve = Passenger.from("Eve", "Jackson", 95); + Passenger fred = Passenger.from("Fred", "Bloggs", 22); + Passenger siya = Passenger.from("Siya", "Kolisi", 85); + Passenger ricki = Passenger.from("Ricki", "Bobbie", 36); + + List passengers = repository.findByFirstNameIgnoreCase("FRED"); + + assertThat(passengers, contains(fred)); + assertThat(passengers, not(contains(eve))); + assertThat(passengers, not(contains(siya))); + assertThat(passengers, not(contains(jill))); + assertThat(passengers, not(contains(ricki))); + + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java new file mode 100644 index 0000000000..24880a5dff --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/entitygraph/EntityGraphIntegrationTest.java @@ -0,0 +1,39 @@ +package com.baeldung.entitygraph; + +import static org.assertj.core.api.Assertions.assertThat; + +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 com.baeldung.entitygraph.model.Characteristic; +import com.baeldung.entitygraph.model.Item; +import com.baeldung.entitygraph.repository.CharacteristicsRepository; +import com.baeldung.entitygraph.repository.ItemRepository; + +@DataJpaTest +@RunWith(SpringRunner.class) +@Sql(scripts = "/entitygraph-data.sql") +public class EntityGraphIntegrationTest { + + @Autowired + private ItemRepository itemRepo; + + @Autowired + private CharacteristicsRepository characteristicsRepo; + + @Test + public void givenEntityGraph_whenCalled_shouldRetrunDefinedFields() { + Item item = itemRepo.findByName("Table"); + assertThat(item.getId()).isEqualTo(1L); + } + + @Test + public void givenAdhocEntityGraph_whenCalled_shouldRetrunDefinedFields() { + Characteristic characteristic = characteristicsRepo.findByType("Rigid"); + assertThat(characteristic.getId()).isEqualTo(1L); + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java new file mode 100644 index 0000000000..d99f6671a3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/exists/CarRepositoryIntegrationTest.java @@ -0,0 +1,87 @@ +package com.baeldung.exists; + +import com.baeldung.Application; +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.context.SpringBootTest; +import org.springframework.data.domain.Example; +import org.springframework.data.domain.ExampleMatcher; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatchers.ignoreCase; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {Application.class}) +public class CarRepositoryIntegrationTest { + + @Autowired + private CarRepository repository; + private int searchId; + + @Before + public void setup() { + List cars = repository.saveAll(Arrays.asList(new Car(200, "BMW"), new Car(300, "Audi"))); + searchId = cars.get(0).getId(); + } + + @After + public void teardown() { + repository.deleteAll(); + } + + @Test + public void whenIdIsCorrect_thenExistsShouldReturnTrue() { + assertThat(repository.existsById(searchId)).isTrue(); + } + + @Test + public void givenExample_whenExists_thenIsTrue() { + ExampleMatcher modelMatcher = ExampleMatcher.matching() + .withIgnorePaths("id") // must explicitly ignore -> PK + .withMatcher("model", ignoreCase()); + Car probe = new Car(); + probe.setModel("bmw"); + + Example example = Example.of(probe, modelMatcher); + + assertThat(repository.exists(example)).isTrue(); + } + + @Test + public void givenPower_whenExists_thenIsFalse() { + assertThat(repository.existsCarByPower(200)).isTrue(); + assertThat(repository.existsCarByPower(800)).isFalse(); + } + + @Test + public void existsByDerivedQuery_byModel() { + assertThat(repository.existsCarByModel("Audi")).isTrue(); + assertThat(repository.existsCarByModel("audi")).isFalse(); + assertThat(repository.existsCarByModel("AUDI")).isFalse(); + assertThat(repository.existsCarByModel("")).isFalse(); + } + + @Test + public void givenModelName_whenExistsExact_thenIsTrue() { + assertThat(repository.existsCarExactCustomQuery("BMW")).isTrue(); + assertThat(repository.existsCarExactCustomQuery("Bmw")).isFalse(); + assertThat(repository.existsCarExactCustomQuery("bmw")).isFalse(); + assertThat(repository.existsCarExactCustomQuery("")).isFalse(); + } + + @Test + public void givenModelName_whenExistsLike_thenIsTrue() { + assertThat(repository.existsCarLikeCustomQuery("BMW")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("Bmw")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("bmw")).isTrue(); + assertThat(repository.existsCarLikeCustomQuery("")).isFalse(); + } + +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java new file mode 100644 index 0000000000..9b0d23f3e4 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java @@ -0,0 +1,142 @@ +package com.baeldung.joins; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.baeldung.joins.model.Department; +import com.baeldung.joins.model.Phone; +import java.util.Collection; +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@DataJpaTest +@ActiveProfiles("joins") +public class JpaJoinsIntegrationTest { + + @PersistenceContext + private EntityManager entityManager; + + @Test + public void whenPathExpressionIsUsedForSingleValuedAssociation_thenCreatesImplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT e.department FROM Employee e", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e JOIN e.department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenInnerJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e INNER JOIN e.department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenEntitiesAreListedInFromAndMatchedInWhere_ThenCreatesJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d WHERE e.department = d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenEntitiesAreListedInFrom_ThenCreatesCartesianProduct() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(9); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Management", "Infra", "Accounting", "Management", "Infra", "Accounting", "Management"); + } + + @Test + public void whenCollectionValuedAssociationIsJoined_ThenCanSelect() { + TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph WHERE ph LIKE '1%'", Phone.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(1); + } + + @Test + public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() { + TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.department d JOIN e.phones ph WHERE d.name IS NOT NULL", Phone.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("number") + .containsOnly("111", "222", "333"); + } + + @Test + public void whenLeftKeywordIsSpecified_thenCreatesOuterJoinAndIncludesNonMatched() { + TypedQuery query = entityManager.createQuery("SELECT DISTINCT d FROM Department d LEFT JOIN d.employees e", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Management"); + } + + @Test + public void whenFetchKeywordIsSpecified_ThenCreatesFetchJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(3); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting"); + } + + @Test + public void whenLeftAndFetchKeywordsAreSpecified_ThenCreatesOuterFetchJoin() { + TypedQuery query = entityManager.createQuery("SELECT d FROM Department d LEFT JOIN FETCH d.employees", Department.class); + + List resultList = query.getResultList(); + + assertThat(resultList).hasSize(4); + assertThat(resultList).extracting("name") + .containsOnly("Infra", "Accounting", "Accounting", "Management"); + } + + @Test + public void whenCollectionValuedAssociationIsSpecifiedInSelect_ThenReturnsCollections() { + TypedQuery query = entityManager.createQuery("SELECT e.phones FROM Employee e", Collection.class); + + List resultList = query.getResultList(); + + assertThat(resultList).extracting("number").containsOnly("111", "222", "333"); + } +} diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/entitygraph-data.sql b/persistence-modules/spring-data-jpa-query/src/test/resources/entitygraph-data.sql new file mode 100644 index 0000000000..685ec2c605 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/entitygraph-data.sql @@ -0,0 +1,7 @@ +INSERT INTO Item(id,name) VALUES (1,'Table'); +INSERT INTO Item(id,name) VALUES (2,'Bottle'); + +INSERT INTO Characteristic(id,item_id, type) VALUES (1,1,'Rigid'); +INSERT INTO Characteristic(id,item_id,type) VALUES (2,1,'Big'); +INSERT INTO Characteristic(id,item_id,type) VALUES (3,2,'Fragile'); +INSERT INTO Characteristic(id,item_id,type) VALUES (4,2,'Small'); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/projection-clean-up-data.sql b/persistence-modules/spring-data-jpa-query/src/test/resources/projection-clean-up-data.sql new file mode 100644 index 0000000000..d34f6f0636 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/projection-clean-up-data.sql @@ -0,0 +1,2 @@ +DELETE FROM address; +DELETE FROM person; \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/projection-insert-data.sql b/persistence-modules/spring-data-jpa-query/src/test/resources/projection-insert-data.sql new file mode 100644 index 0000000000..544dcc4b88 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/projection-insert-data.sql @@ -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'); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/test-aggregation-data.sql b/persistence-modules/spring-data-jpa-query/src/test/resources/test-aggregation-data.sql new file mode 100644 index 0000000000..12409a124e --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/test-aggregation-data.sql @@ -0,0 +1,7 @@ +INSERT INTO post (id, title, content) VALUES (1, 'Comment 1', 'Content 1'); +INSERT INTO post (id, title, content) VALUES (2, 'Comment 2', 'Content 2'); +INSERT INTO post (id, title, content) VALUES (3, 'Comment 3', 'Content 3'); +INSERT INTO comment (id, year, approved, content, post_id) VALUES (1, 2019, false, 'Comment 1', 1); +INSERT INTO comment (id, year, approved, content, post_id) VALUES (2, 2018, true, 'Comment 2', 1); +INSERT INTO comment (id, year, approved, content, post_id) VALUES (3, 2018, true, 'Comment 3', 2); +INSERT INTO comment (id, year, approved, content, post_id) VALUES (4, 2017, false, 'Comment 4', 3); \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query/src/test/resources/test-fruit-data.sql b/persistence-modules/spring-data-jpa-query/src/test/resources/test-fruit-data.sql new file mode 100644 index 0000000000..d99f42e5a7 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query/src/test/resources/test-fruit-data.sql @@ -0,0 +1,6 @@ +truncate table fruit; + +insert into fruit(id,name,color) values (1,'apple','red'); +insert into fruit(id,name,color) values (2,'custard apple','green'); +insert into fruit(id,name,color) values (3,'mango','yellow'); +insert into fruit(id,name,color) values (4,'guava','green'); \ No newline at end of file