diff --git a/persistence-modules/blaze-persistence/README.md b/persistence-modules/blaze-persistence/README.md new file mode 100644 index 0000000000..7d843af9ea --- /dev/null +++ b/persistence-modules/blaze-persistence/README.md @@ -0,0 +1 @@ +### Relevant Articles: diff --git a/persistence-modules/blaze-persistence/pom.xml b/persistence-modules/blaze-persistence/pom.xml new file mode 100644 index 0000000000..cc57785fe9 --- /dev/null +++ b/persistence-modules/blaze-persistence/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + blaze-persistence + 1.0-SNAPSHOT + blaze-persistence + + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + + + UTF-8 + 1.8 + 1.8 + 1.6.8 + + + + + + com.blazebit + blaze-persistence-bom + ${blaze-persistence.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + com.blazebit + blaze-persistence-core-api + + + com.blazebit + blaze-persistence-core-impl + + + com.blazebit + blaze-persistence-integration-hibernate-5.4 + + + + + com.blazebit + blaze-persistence-entity-view-api + + + com.blazebit + blaze-persistence-entity-view-impl + + + com.blazebit + blaze-persistence-entity-view-processor + + + + + com.blazebit + blaze-persistence-integration-entity-view-spring + + + com.blazebit + blaze-persistence-integration-spring-data-2.4 + + + + + org.springframework + spring-context + + + org.springframework + spring-orm + + + + com.h2database + h2 + + + + + org.springframework + spring-test + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/BlazePersistenceApplication.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/BlazePersistenceApplication.java new file mode 100644 index 0000000000..e2976aaf37 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/BlazePersistenceApplication.java @@ -0,0 +1,57 @@ +package com.baeldung; + +import com.baeldung.model.Person; +import com.baeldung.model.Post; +import com.baeldung.repository.PersonRepository; +import com.baeldung.repository.PostRepository; +import com.baeldung.repository.PostViewRepository; +import com.baeldung.view.PostWithAuthorView; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class BlazePersistenceApplication implements CommandLineRunner { + + private static final Logger logger = LoggerFactory.getLogger(BlazePersistenceApplication.class); + + @Autowired + private PersonRepository personRepository; + + @Autowired + private PostRepository postRepository; + + @Autowired + private PostViewRepository postViewRepository; + + public static void main(String[] args) { + SpringApplication.run(BlazePersistenceApplication.class, args); + } + + @Override + public void run(String... args) { + + logger.info("All Posts:"); + Iterable posts = postRepository.findAll(); + posts.forEach(p -> logger.info(String.valueOf(p))); + + logger.info("Posts with title 'Spring' or author 'Peter':"); + Iterable postsFiltered = postRepository.findBy("Spring", "Peter"); + postsFiltered.forEach(p -> logger.info(String.valueOf(p))); + + logger.info("Find all post with author view:"); + Iterable postsView = postViewRepository.findAll(); + postsView.forEach(p -> logger.info(String.valueOf(p))); + + logger.info("Person with at least two posts:"); + Iterable personIterable = personRepository.find(); + personIterable.forEach(p -> logger.info(String.valueOf(p))); + + logger.info("All Persons:"); + Iterable personIterableAll = personRepository.findAll(); + personIterableAll.forEach(p -> logger.info(String.valueOf(p))); + } +} \ No newline at end of file diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/config/BlazePersistenceConfiguration.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/config/BlazePersistenceConfiguration.java new file mode 100644 index 0000000000..0ec2e881ed --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/config/BlazePersistenceConfiguration.java @@ -0,0 +1,35 @@ +package com.baeldung.config; + +import com.blazebit.persistence.Criteria; +import com.blazebit.persistence.CriteriaBuilderFactory; +import com.blazebit.persistence.integration.view.spring.EnableEntityViews; +import com.blazebit.persistence.spi.CriteriaBuilderConfiguration; +import com.blazebit.persistence.spring.data.repository.config.EnableBlazeRepositories; +import com.blazebit.persistence.view.EntityViewManager; +import com.blazebit.persistence.view.spi.EntityViewConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.persistence.EntityManagerFactory; + +@Configuration +@EnableEntityViews(basePackages = {"com.baeldung.view"}) +@EnableBlazeRepositories(basePackages = "com.baeldung.repository") +public class BlazePersistenceConfiguration { + + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Bean + public CriteriaBuilderFactory createCriteriaBuilderFactory() { + CriteriaBuilderConfiguration config = Criteria.getDefault(); + return config.createCriteriaBuilderFactory(entityManagerFactory); + } + + @Bean + public EntityViewManager createEntityViewManager(CriteriaBuilderFactory criteriaBuilderFactory, + EntityViewConfiguration entityViewConfiguration) { + return entityViewConfiguration.createEntityViewManager(criteriaBuilderFactory); + } +} \ No newline at end of file diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Person.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Person.java new file mode 100644 index 0000000000..a6daade80d --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Person.java @@ -0,0 +1,72 @@ +package com.baeldung.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class Person { + + @Id + @GeneratedValue + private Long id; + + private String name; + + private int age; + + @OneToMany(mappedBy = "author") + private Set posts = new HashSet<>(); + + public Person() { + } + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + 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 Set getPosts() { + return posts; + } + + public void setPosts(Set posts) { + this.posts = posts; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "Person{" + + "id=" + id + + ", name='" + name + '\'' + + ", age=" + age + + '}'; + } +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Post.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Post.java new file mode 100644 index 0000000000..6fc10dc730 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/model/Post.java @@ -0,0 +1,68 @@ +package com.baeldung.model; + +import javax.persistence.*; + +@Entity +public class Post { + + @Id + @GeneratedValue + private Long id; + + private String title; + + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + private Person author; + + public Post() { + } + + public Post(String title, String content, Person author) { + this.title = title; + this.content = content; + this.author = author; + } + + public Long getId() { + return id; + } + + public void setId(Long 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 Person getAuthor() { + return author; + } + + public void setAuthor(Person author) { + this.author = author; + } + + @Override + public String toString() { + return "Post{" + + "id=" + id + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + '}'; + } +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PersonRepository.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PersonRepository.java new file mode 100644 index 0000000000..12b197e8be --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PersonRepository.java @@ -0,0 +1,47 @@ +package com.baeldung.repository; + +import com.baeldung.model.Person; +import com.baeldung.model.Post; +import com.blazebit.persistence.CriteriaBuilder; +import com.blazebit.persistence.CriteriaBuilderFactory; +import org.springframework.stereotype.Repository; + +import javax.persistence.EntityManager; +import javax.transaction.Transactional; + +@Repository +@Transactional +public class PersonRepository { + + private final EntityManager entityManager; + + private final CriteriaBuilderFactory builderFactory; + + public PersonRepository(EntityManager entityManager, CriteriaBuilderFactory builderFactory) { + this.entityManager = entityManager; + this.builderFactory = builderFactory; + } + + public Iterable findPostsByPerson() { + CriteriaBuilder postCriteriaBuilder = builderFactory.create(entityManager, Post.class) + .from(Person.class, "person") + .select("person.posts"); + return postCriteriaBuilder.getResultList(); + } + + public Iterable findAll() { + return builderFactory.create(entityManager, Person.class).getResultList(); + } + + public Iterable find() { + CriteriaBuilder personCriteriaBuilder = builderFactory.create(entityManager, Person.class, "p") + .where("p.age") + .betweenExpression("18") + .andExpression("40") + .where("SIZE(p.posts)").geExpression("2") + .orderByAsc("p.name") + .orderByAsc("p.id"); + return personCriteriaBuilder.getResultList(); + } + +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostRepository.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostRepository.java new file mode 100644 index 0000000000..cf7edffe62 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostRepository.java @@ -0,0 +1,48 @@ +package com.baeldung.repository; + +import com.baeldung.model.Post; +import com.baeldung.view.PostWithAuthorView; +import com.blazebit.persistence.CriteriaBuilder; +import com.blazebit.persistence.CriteriaBuilderFactory; +import com.blazebit.persistence.view.EntityViewManager; +import com.blazebit.persistence.view.EntityViewSetting; +import org.springframework.stereotype.Repository; + +import javax.persistence.EntityManager; +import javax.transaction.Transactional; + +@Repository +@Transactional +public class PostRepository { + + private final EntityManager entityManager; + + private final CriteriaBuilderFactory builderFactory; + + private final EntityViewManager viewManager; + + public PostRepository(EntityManager entityManager, CriteriaBuilderFactory builderFactory, + EntityViewManager viewManager) { + this.entityManager = entityManager; + this.builderFactory = builderFactory; + this.viewManager = viewManager; + } + + public Iterable findAll() { + return builderFactory.create(entityManager, Post.class).getResultList(); + } + + public Iterable findBy(final String title, final String authorName) { + CriteriaBuilder postCriteriaBuilder = builderFactory.create(entityManager, Post.class, "p") + .whereOr() + .where("p.title").like().value(title + "%").noEscape() + .where("p.author.name").eq(authorName) + .endOr(); + + CriteriaBuilder postWithAuthorViewCriteriaBuilder = + viewManager.applySetting(EntityViewSetting + .create(PostWithAuthorView.class), postCriteriaBuilder); + + return postWithAuthorViewCriteriaBuilder.getResultList(); + } +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostViewRepository.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostViewRepository.java new file mode 100644 index 0000000000..ef241c73a2 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/repository/PostViewRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.repository; + +import com.baeldung.view.PostWithAuthorView; +import com.blazebit.persistence.spring.data.repository.EntityViewRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +@Repository +@Transactional(readOnly = true) +public interface PostViewRepository extends EntityViewRepository { +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PersonView.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PersonView.java new file mode 100644 index 0000000000..e9dd184629 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PersonView.java @@ -0,0 +1,16 @@ +package com.baeldung.view; + +import com.baeldung.model.Person; +import com.blazebit.persistence.view.EntityView; +import com.blazebit.persistence.view.IdMapping; + +@EntityView(Person.class) +public interface PersonView { + + @IdMapping + Long getId(); + + int getAge(); + + String getName(); +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostView.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostView.java new file mode 100644 index 0000000000..b335cda385 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostView.java @@ -0,0 +1,18 @@ +package com.baeldung.view; + +import com.baeldung.model.Post; +import com.blazebit.persistence.view.EntityView; +import com.blazebit.persistence.view.IdMapping; +import com.blazebit.persistence.view.Mapping; + +@EntityView(Post.class) +public interface PostView { + + @IdMapping + Long getId(); + + @Mapping("UPPER(title)") + String getTitle(); + + String getContent(); +} diff --git a/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostWithAuthorView.java b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostWithAuthorView.java new file mode 100644 index 0000000000..8a34a4e34a --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/java/com/baeldung/view/PostWithAuthorView.java @@ -0,0 +1,10 @@ +package com.baeldung.view; + +import com.baeldung.model.Post; +import com.blazebit.persistence.view.EntityView; + +@EntityView(Post.class) +public interface PostWithAuthorView extends PostView { + PersonView getAuthor(); + +} diff --git a/persistence-modules/blaze-persistence/src/main/resources/application.properties b/persistence-modules/blaze-persistence/src/main/resources/application.properties new file mode 100644 index 0000000000..de4a62720a --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/resources/application.properties @@ -0,0 +1,9 @@ +spring.h2.console.enabled=true +spring.jpa.show-sql=true +logging.level.org.hibernate.SQL=DEBUG +spring.jpa.hibernate.ddl-auto=create +spring.datasource.url=jdbc:h2:mem:test +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=sa +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/persistence-modules/blaze-persistence/src/main/resources/data.sql b/persistence-modules/blaze-persistence/src/main/resources/data.sql new file mode 100644 index 0000000000..0ed609a2a4 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/main/resources/data.sql @@ -0,0 +1,11 @@ +INSERT INTO Person(id, name, age) VALUES(1, 'Peter', 18); +INSERT INTO Person(id, name, age) VALUES(2, 'Emily', 36); +INSERT INTO Person(id, name, age) VALUES(3, 'John', 27); + +INSERT INTO Post(id, title, content, author_id) VALUES(1, 'Blaze Persistence', 'Blaze Content', 1); +INSERT INTO Post(id, title, content, author_id) VALUES(2, 'Jacoco', 'Jacoco Content', 1); +INSERT INTO Post(id, title, content, author_id) VALUES(3, 'Spring', 'Spring Content', 2); +INSERT INTO Post(id, title, content, author_id) VALUES(4, 'Spring Boot', 'Spring Boot Content', 3); +INSERT INTO Post(id, title, content, author_id) VALUES(5, 'Java 17', 'Java Content', 3); +INSERT INTO Post(id, title, content, author_id) VALUES(6, 'Functional Programming', 'Functional Programming Content', 3); +INSERT INTO Post(id, title, content, author_id) VALUES(7, 'Unit Testing', 'Unit Testing Content', 3); \ No newline at end of file diff --git a/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PersonUnitTest.java b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PersonUnitTest.java new file mode 100644 index 0000000000..16434d52d0 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PersonUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung; + +import com.baeldung.model.Person; +import com.baeldung.model.Post; +import com.baeldung.repository.PersonRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ContextConfiguration(classes = TestContextConfig.class) +@ExtendWith(SpringExtension.class) +public class PersonUnitTest { + + @Autowired + private PersonRepository personRepository; + + @Test + public void whenFind_thenReturnCorrectListSize() { + final Iterable listIterable = personRepository.find(); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(2, list.size()); + assertEquals("John", list.get(0).getName()); + } + + @Test + public void whenFindAll_thenReturnCorrectListSize() { + final Iterable listIterable = personRepository.findAll(); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(3, list.size()); + } + + @Test + public void whenFindPostsByPerson_thenReturnCorrectListSize() { + final Iterable listIterable = personRepository.findPostsByPerson(); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(7, list.size()); + } + +} diff --git a/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PostUnitTest.java b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PostUnitTest.java new file mode 100644 index 0000000000..0af01de088 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/PostUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung; + +import com.baeldung.model.Post; +import com.baeldung.repository.PostRepository; +import com.baeldung.repository.PostViewRepository; +import com.baeldung.view.PostView; +import com.baeldung.view.PostWithAuthorView; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ContextConfiguration(classes = TestContextConfig.class) +@ExtendWith(SpringExtension.class) +public class PostUnitTest { + + @Autowired + private PostViewRepository postViewRepository; + + @Autowired + private PostRepository postRepository; + + @Test + public void whenFindAll_thenReturnCorrectListViewSize() { + final Iterable listIterable = postViewRepository.findAll(); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(7, list.size()); + } + + @Test + public void givenPostIdAndAuthorName_whenFind_thenReturnCorrectResult() { + final Iterable listIterable = + postRepository.findBy("Spring", "Peter"); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(4, list.size()); + } + + @Test + public void whenFindAll_thenReturnCorrectListSize() { + final Iterable listIterable = postRepository.findAll(); + final List list = new ArrayList<>(); + listIterable.forEach(list::add); + assertEquals(7, list.size()); + } + +} diff --git a/persistence-modules/blaze-persistence/src/test/java/com/baeldung/TestContextConfig.java b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/TestContextConfig.java new file mode 100644 index 0000000000..1df1fb21d9 --- /dev/null +++ b/persistence-modules/blaze-persistence/src/test/java/com/baeldung/TestContextConfig.java @@ -0,0 +1,15 @@ +package com.baeldung; + +import com.blazebit.persistence.integration.view.spring.EnableEntityViews; +import com.blazebit.persistence.spring.data.repository.config.EnableBlazeRepositories; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.baeldung") +@EnableEntityViews(basePackages = {"com.baeldung.view"}) +@EnableBlazeRepositories(basePackages = "com.baeldung.repository") +public class TestContextConfig { + + +} diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index bff23cffc1..c17e793dbc 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -18,6 +18,7 @@ apache-bookkeeper apache-cayenne apache-derby + blaze-persistence core-java-persistence core-java-persistence-2 deltaspike