Merge branch 'master' into bael-16656
This commit is contained in:
@@ -8,3 +8,4 @@ This module contains articles about Object-relational Mapping (ORM) with Hiberna
|
||||
- [Difference Between @Size, @Length, and @Column(length=value)](https://www.baeldung.com/jpa-size-length-column-differences)
|
||||
- [Hibernate Validator Specific Constraints](https://www.baeldung.com/hibernate-validator-constraints)
|
||||
- [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many)
|
||||
- [Hibernate @WhereJoinTable Annotation](https://www.baeldung.com/hibernate-wherejointable)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<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>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>hibernate-parameters</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
<name>hibernate-parameters</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Hibernate tutorial illustrating the use of named parameters</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<version>5.4.4.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.196</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<testResources>
|
||||
<testResource>
|
||||
<filtering>false</filtering>
|
||||
<directory>src/test/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</testResource>
|
||||
<testResource>
|
||||
<directory>src/test/resources</directory>
|
||||
</testResource>
|
||||
</testResources>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<hibernate-mapping package="com.baeldung.hibernate_parameters">
|
||||
|
||||
<class name="Event" table="EVENTS">
|
||||
<id name="id" column="EVENT_ID">
|
||||
<generator class="increment"/>
|
||||
</id>
|
||||
<property name="title"/>
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package com.baeldung.hibernate_parameters;
|
||||
|
||||
public class Event {
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
public Event() {
|
||||
}
|
||||
|
||||
public Event(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
-72
@@ -1,72 +0,0 @@
|
||||
package com.baeldung.hibernate_parameters;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.query.Query;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public class NamedParameterUnitTest {
|
||||
private SessionFactory sessionFactory;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
|
||||
.configure()
|
||||
.build();
|
||||
try {
|
||||
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
session.save(new Event("Event 1"));
|
||||
session.save(new Event("Event 2"));
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
} catch (Exception e) {
|
||||
StandardServiceRegistryBuilder.destroy(registry);
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (sessionFactory != null) {
|
||||
sessionFactory.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenNamedParameterProvided_thenCorrect() {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);
|
||||
|
||||
// This binds the value "Event1" to the parameter :eventTitle
|
||||
query.setParameter("eventTitle", "Event 1");
|
||||
|
||||
assertEquals(1, query.list().size());
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test(expected = org.hibernate.QueryException.class)
|
||||
public void whenNamedParameterMissing_thenThrowsQueryException() {
|
||||
Session session = sessionFactory.openSession();
|
||||
session.beginTransaction();
|
||||
Query<Event> query = session.createQuery("from Event E WHERE E.title = :eventTitle", Event.class);
|
||||
|
||||
try {
|
||||
query.list();
|
||||
fail("We are expecting an exception!");
|
||||
} finally {
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!DOCTYPE hibernate-configuration PUBLIC
|
||||
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||
|
||||
<hibernate-configuration>
|
||||
|
||||
<session-factory>
|
||||
<property name="connection.driver_class">org.h2.Driver</property>
|
||||
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
|
||||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"/>
|
||||
|
||||
<property name="connection.pool_size">1</property>
|
||||
|
||||
<property name="dialect">org.hibernate.dialect.H2Dialect</property>
|
||||
|
||||
<property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
|
||||
|
||||
<property name="show_sql">true</property>
|
||||
|
||||
<property name="hbm2ddl.auto">create</property>
|
||||
|
||||
<mapping resource="com/baeldung/hibernate_parameters/Event.hbm.xml"/>
|
||||
|
||||
</session-factory>
|
||||
|
||||
</hibernate-configuration>
|
||||
-1
@@ -26,7 +26,6 @@ public class CustomClassIntegrationTest {
|
||||
public void setUp() throws IOException {
|
||||
session = HibernateUtil.getSessionFactory().openSession();
|
||||
transaction = session.beginTransaction();
|
||||
session.createNativeQuery("delete from manager").executeUpdate();
|
||||
session.createNativeQuery("delete from department").executeUpdate();
|
||||
Department department = new Department("Sales");
|
||||
DeptEmployee employee = new DeptEmployee("John Smith", "001", department);
|
||||
|
||||
@@ -10,4 +10,6 @@ This module contains articles about the Java Persistence API (JPA) in Java.
|
||||
- [Types of JPA Queries](https://www.baeldung.com/jpa-queries)
|
||||
- [JPA/Hibernate Projections](https://www.baeldung.com/jpa-hibernate-projections)
|
||||
- [Combining JPA And/Or Criteria Predicates](https://www.baeldung.com/jpa-and-or-criteria-predicates)
|
||||
- More articles: [[<-- prev]](/java-jpa)
|
||||
- [JPA Annotation for the PostgreSQL TEXT Type](https://www.baeldung.com/jpa-annotation-postgresql-text-type)
|
||||
- [Mapping a Single Entity to Multiple Tables in JPA](https://www.baeldung.com/jpa-mapping-single-entity-to-multiple-tables)
|
||||
- More articles: [[<-- prev]](/java-jpa)
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
|
||||
- [Introduction to Sirix](https://www.baeldung.com/introduction-to-sirix)
|
||||
- [A Guide to SirixDB](https://www.baeldung.com/sirix)
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi)
|
||||
@@ -26,11 +26,6 @@
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -17,14 +17,17 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
@@ -35,6 +38,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
@@ -99,6 +103,7 @@
|
||||
<validation-api.version>2.0.1.Final</validation-api.version>
|
||||
<derby.version>10.13.1.1</derby.version>
|
||||
<hsqldb.version>2.3.4</hsqldb.version>
|
||||
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
+85
@@ -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());
|
||||
}
|
||||
}
|
||||
+75
@@ -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<Comment> 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<Comment> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(List<Comment> 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());
|
||||
}
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.aggregation.model.custom;
|
||||
|
||||
public interface ICommentCount {
|
||||
|
||||
Integer getYearComment();
|
||||
|
||||
Long getTotalComment();
|
||||
}
|
||||
+27
@@ -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<Comment, Integer> {
|
||||
|
||||
@Query("SELECT c.year, COUNT(c.year) FROM Comment AS c GROUP BY c.year ORDER BY c.year DESC")
|
||||
List<Object[]> 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<CommentCount> 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<ICommentCount> 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<ICommentCount> countTotalCommentsByYearNative();
|
||||
|
||||
}
|
||||
+107
@@ -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<Object[]> 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<CommentCount> 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<ICommentCount> 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<ICommentCount> 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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
@@ -18,6 +18,10 @@
|
||||
<dependencies>
|
||||
|
||||
<!-- Prod Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
@@ -39,26 +43,20 @@
|
||||
<groupId>net.ttddyy</groupId>
|
||||
<artifactId>datasource-proxy</artifactId>
|
||||
<version>${datasource-proxy.version}</version>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Test Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${testcontainers.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
@@ -93,5 +91,7 @@
|
||||
<guava.version>21.0</guava.version>
|
||||
<testcontainers.version>1.12.2</testcontainers.version>
|
||||
<postgresql.version>42.2.8</postgresql.version>
|
||||
<testcontainers.version>1.12.2</testcontainers.version>
|
||||
<h2.version>1.4.200</h2.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.tx;
|
||||
package com.baeldung.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
@ElementCollection
|
||||
private Set<String> permissions;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(Set<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.repository;
|
||||
|
||||
import com.baeldung.model.User;
|
||||
import org.springframework.data.jpa.repository.EntityGraph;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
@EntityGraph(attributePaths = "permissions")
|
||||
Optional<User> findDetailedByUsername(String username);
|
||||
|
||||
Optional<User> findSummaryByUsername(String username);
|
||||
|
||||
Optional<User> findByUsername(String username);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.service;
|
||||
|
||||
import com.baeldung.model.User;
|
||||
import com.baeldung.repository.UserRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class SimpleUserService implements UserService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public SimpleUserService(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public Optional<User> findOne(String username) {
|
||||
return userRepository.findDetailedByUsername(username);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.service;
|
||||
|
||||
import com.baeldung.model.User;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UserService {
|
||||
Optional<User> findOne(String username);
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.baeldung.web;
|
||||
|
||||
import com.baeldung.model.User;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class DetailedUserDto {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private Set<String> permissions;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Set<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(Set<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public static DetailedUserDto fromEntity(User user) {
|
||||
DetailedUserDto detailed = new DetailedUserDto();
|
||||
detailed.setId(user.getId());
|
||||
detailed.setUsername(user.getUsername());
|
||||
detailed.setPermissions(user.getPermissions());
|
||||
|
||||
return detailed;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.baeldung.web;
|
||||
|
||||
import com.baeldung.service.UserService;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/users")
|
||||
public class UserController {
|
||||
|
||||
private final UserService userService;
|
||||
|
||||
public UserController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping("/{username}")
|
||||
public ResponseEntity<?> findOne(@PathVariable String username) {
|
||||
return userService.findOne(username)
|
||||
.map(DetailedUserDto::fromEntity)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.osiv;
|
||||
|
||||
import com.baeldung.model.User;
|
||||
import com.baeldung.repository.UserRepository;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
class UserControllerIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
User user = new User();
|
||||
user.setUsername("root");
|
||||
user.setPermissions(new HashSet<>(Arrays.asList("PERM_READ", "PERM_WRITE")));
|
||||
|
||||
userRepository.save(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenTheUserExists_WhenOsivIsEnabled_ThenLazyInitWorkEverywhere() throws Exception {
|
||||
mockMvc.perform(get("/users/root"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.username").value("root"))
|
||||
.andExpect(jsonPath("$.permissions", containsInAnyOrder("PERM_READ", "PERM_WRITE")));
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void flushDb() {
|
||||
userRepository.deleteAll();
|
||||
}
|
||||
}
|
||||
+1
-20
@@ -1,10 +1,10 @@
|
||||
package com.baeldung.tx;
|
||||
|
||||
import com.baeldung.model.Payment;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -14,27 +14,17 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE;
|
||||
import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED;
|
||||
|
||||
@DataJpaTest
|
||||
@Testcontainers
|
||||
@ActiveProfiles("test")
|
||||
@AutoConfigureTestDatabase(replace = NONE)
|
||||
@Transactional(propagation = NOT_SUPPORTED)
|
||||
class ManualTransactionIntegrationTest {
|
||||
|
||||
@Container
|
||||
private static PostgreSQLContainer<?> pg = initPostgres();
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@@ -159,13 +149,4 @@ class ManualTransactionIntegrationTest {
|
||||
.getResultList()).hasSize(1);
|
||||
}
|
||||
|
||||
private static PostgreSQLContainer<?> initPostgres() {
|
||||
PostgreSQLContainer<?> pg = new PostgreSQLContainer<>("postgres:11.1")
|
||||
.withDatabaseName("baeldung")
|
||||
.withUsername("test")
|
||||
.withPassword("test");
|
||||
pg.setPortBindings(singletonList("54320:5432"));
|
||||
|
||||
return pg;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,4 +1,2 @@
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.datasource.url=jdbc:postgresql://localhost:54320/baeldung
|
||||
spring.datasource.username=test
|
||||
spring.datasource.password=test
|
||||
spring.datasource.url=jdbc:h2:mem:jpa3
|
||||
@@ -87,7 +87,8 @@
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<verbose>true</verbose>
|
||||
<fork>true</fork>
|
||||
<fork>false</fork>
|
||||
<forkCount>0</forkCount>
|
||||
<argLine>-Xmx1024m</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class RedisKeyCommandsIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() throws IOException {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build();
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public class RedisTemplateListOpsIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() throws IOException {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxheap 128M").build();
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ public class RedisTemplateValueOpsIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() throws IOException {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build();
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ public class RedisMessageListenerIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() throws IOException {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxheap 256M").build();
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class RedisMessageListenerIntegrationTest {
|
||||
public void testOnMessage() throws Exception {
|
||||
String message = "Message " + UUID.randomUUID();
|
||||
redisMessagePublisher.publish(message);
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(1000);
|
||||
assertTrue(RedisMessageSubscriber.messageList.get(0).contains(message));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -34,7 +34,7 @@ public class StudentRepositoryIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() throws IOException {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxheap 128M").build();
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 128M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
|
||||
+20
-1
@@ -1,16 +1,35 @@
|
||||
package org.baeldung;
|
||||
|
||||
import com.baeldung.spring.data.redis.config.RedisConfig;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
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 redis.embedded.RedisServerBuilder;
|
||||
|
||||
import com.baeldung.spring.data.redis.config.RedisConfig;
|
||||
import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFORE_CLASS;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext(classMode = BEFORE_CLASS)
|
||||
@ContextConfiguration(classes = RedisConfig.class)
|
||||
public class SpringContextIntegrationTest {
|
||||
|
||||
private static redis.embedded.RedisServer redisServer;
|
||||
|
||||
@BeforeClass
|
||||
public static void startRedisServer() {
|
||||
redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build();
|
||||
redisServer.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopRedisServer() {
|
||||
redisServer.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
- [Transactions with Spring 4 and JPA](http://www.baeldung.com/transaction-configuration-with-jpa-and-spring)
|
||||
- [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries)
|
||||
- [Many-To-Many Relationship in JPA](https://www.baeldung.com/jpa-many-to-many)
|
||||
- [Spring Persistence (Hibernate and JPA) with a JNDI datasource](https://www.baeldung.com/spring-persistence-hibernate-and-jpa-with-a-jndi-datasource/)
|
||||
|
||||
|
||||
### Eclipse Config
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
- [Introduction to Spring Data JPA](http://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)
|
||||
- [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query)
|
||||
- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate)
|
||||
- [Transaction Propagation and Isolation in Spring @Transactional](https://www.baeldung.com/spring-transactional-propagation-isolation)
|
||||
|
||||
### Eclipse Config
|
||||
After importing the project into Eclipse, you may see the following error:
|
||||
|
||||
Reference in New Issue
Block a user