diff --git a/spring-hibernate5/.gitignore b/spring-hibernate5/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-hibernate5/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-hibernate5/pom.xml b/spring-hibernate5/pom.xml
new file mode 100644
index 0000000000..81f8084d74
--- /dev/null
+++ b/spring-hibernate5/pom.xml
@@ -0,0 +1,239 @@
+
+ 4.0.0
+ com.baeldung
+ spring-hibernate5
+ 0.1-SNAPSHOT
+
+ spring-hibernate5
+
+
+
+
+
+
+ org.springframework
+ spring-context
+ ${org.springframework.version}
+
+
+ org.springframework
+ spring-aspects
+ ${org.springframework.version}
+
+
+ org.springframework.security
+ spring-security-core
+ ${org.springframework.security.version}
+
+
+
+
+
+ org.springframework
+ spring-orm
+ ${org.springframework.version}
+
+
+ org.springframework.data
+ spring-data-jpa
+ ${org.springframework.data.version}
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+
+
+ org.hibernate
+ hibernate-envers
+ ${hibernate-envers.version}
+
+
+ javax.transaction
+ jta
+ ${jta.version}
+
+
+ mysql
+ mysql-connector-java
+ ${mysql-connector-java.version}
+
+
+
+ org.apache.tomcat
+ tomcat-dbcp
+ ${tomcat-dbcp.version}
+
+
+
+
+
+ org.hibernate
+ hibernate-validator
+ ${hibernate-validator.version}
+
+
+ javax.el
+ javax.el-api
+ ${javax.el-api.version}
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+ test
+
+
+
+ org.springframework
+ spring-test
+ ${org.springframework.version}
+ test
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+ org.springframework.security
+ spring-security-test
+ ${org.springframework.security.version}
+ test
+
+
+
+ org.hamcrest
+ hamcrest-core
+ ${org.hamcrest.version}
+ test
+
+
+
+ junit
+ junit-dep
+ 4.11
+ test
+
+
+
+ org.hamcrest
+ hamcrest-library
+ ${org.hamcrest.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+
+ org.hsqldb
+ hsqldb
+ ${hsqldb.version}
+ test
+
+
+
+
+
+ spring-hibernate5
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ 1.8
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 4.3.5.RELEASE
+ 4.2.1.RELEASE
+ 1.10.6.RELEASE
+
+
+ 5.2.8.Final
+ ${hibernate.version}
+ 6.0.5
+ 8.5.11
+ 1.1
+ 2.3.4
+
+
+ 1.7.21
+ 1.1.7
+
+
+ 5.4.0.Final
+ 2.2.5
+
+
+ 21.0
+ 3.5
+
+
+ 1.3
+ 4.12
+ 2.6.8
+
+ 4.4.1
+ 4.5
+
+ 2.9.0
+
+
+ 3.6.0
+ 2.19.1
+ 2.7
+ 1.6.1
+
+
+
+
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java
new file mode 100644
index 0000000000..957207b7e6
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/model/Item.java
@@ -0,0 +1,81 @@
+package com.baeldung.hibernate.criteria.model;
+
+import java.io.Serializable;
+
+public class Item implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private Integer itemId;
+ private String itemName;
+ private String itemDescription;
+ private Integer itemPrice;
+
+ // constructors
+ public Item() {
+
+ }
+
+ public Item(final Integer itemId, final String itemName, final String itemDescription) {
+ super();
+ this.itemId = itemId;
+ this.itemName = itemName;
+ this.itemDescription = itemDescription;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((itemId == null) ? 0 : itemId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Item other = (Item) obj;
+ if (itemId == null) {
+ if (other.itemId != null)
+ return false;
+ } else if (!itemId.equals(other.itemId))
+ return false;
+ return true;
+ }
+
+ public Integer getItemId() {
+ return itemId;
+ }
+
+ public void setItemId(final Integer itemId) {
+ this.itemId = itemId;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(final String itemName) {
+ this.itemName = itemName;
+ }
+
+ public String getItemDescription() {
+ return itemDescription;
+ }
+
+ public Integer getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setItemPrice(final Integer itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public void setItemDescription(final String itemDescription) {
+ this.itemDescription = itemDescription;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java
new file mode 100644
index 0000000000..9024ba9e4b
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/util/HibernateUtil.java
@@ -0,0 +1,17 @@
+package com.baeldung.hibernate.criteria.util;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ public static Session getHibernateSession() {
+
+ final SessionFactory sf = new Configuration().configure("criteria.cfg.xml").buildSessionFactory();
+
+ final Session session = sf.openSession();
+ return session;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java
new file mode 100644
index 0000000000..a854b51753
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java
@@ -0,0 +1,284 @@
+/**
+ * ApplicationViewer is the class that starts the application
+ * First it creates the session object and then creates the
+ * criteria query.
+ *
+ * @author Sandeep Kumar
+ * @version 1.0
+ * @since 01/13/2017
+ */
+
+package com.baeldung.hibernate.criteria.view;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Tuple;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+import com.baeldung.hibernate.criteria.model.Item;
+import com.baeldung.hibernate.criteria.util.HibernateUtil;
+
+public class ApplicationView {
+
+ public ApplicationView() {
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean checkIfCriteriaTimeLower() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ Transaction tx = null;
+
+ // calculate the time taken by criteria
+ final long startTimeCriteria = System.nanoTime();
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%item One%"));
+ final List
- results = session.createQuery(criteriaItem).getResultList();
+ final long endTimeCriteria = System.nanoTime();
+ final long durationCriteria = (endTimeCriteria - startTimeCriteria) / 1000;
+
+ // calculate the time taken by HQL
+ final long startTimeHQL = System.nanoTime();
+ tx = session.beginTransaction();
+ final List
- items = session.createQuery("FROM Item where itemName like '%item One%'").getResultList();
+ final long endTimeHQL = System.nanoTime();
+ final long durationHQL = (endTimeHQL - startTimeHQL) / 1000;
+
+ if (durationCriteria > durationHQL) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ // To get items having price more than 1000
+ public String[] greaterThanCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ final List
- greaterThanItemsList = session.createQuery(criteriaItem).getResultList();
+ final String greaterThanItems[] = new String[greaterThanItemsList.size()];
+ for (int i = 0; i < greaterThanItemsList.size(); i++) {
+ greaterThanItems[i] = greaterThanItemsList.get(i).getItemName();
+ }
+ session.close();
+ return greaterThanItems;
+ }
+
+ // To get items having price less than 1000
+ public String[] lessThanCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.lessThan(rootItem.get("itemPrice"), 1000));
+ final List
- lessThanItemsList = session.createQuery(criteriaItem).getResultList();
+ final String lessThanItems[] = new String[lessThanItemsList.size()];
+ for (int i = 0; i < lessThanItemsList.size(); i++) {
+ lessThanItems[i] = lessThanItemsList.get(i).getItemName();
+ }
+ session.close();
+ return lessThanItems;
+ }
+
+ // To get items whose Name start with Chair
+ public String[] likeCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%chair%"));
+ final List
- likeItemsList = session.createQuery(criteriaItem).getResultList();
+ final String likeItems[] = new String[likeItemsList.size()];
+ for (int i = 0; i < likeItemsList.size(); i++) {
+ likeItems[i] = likeItemsList.get(i).getItemName();
+ }
+ session.close();
+ return likeItems;
+ }
+
+ // Case sensitive search
+ public String[] likeCaseCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.like(rootItem.get("itemName"), "%Chair%"));
+ final List
- ilikeItemsList = session.createQuery(criteriaItem).getResultList();
+ final String ilikeItems[] = new String[ilikeItemsList.size()];
+ for (int i = 0; i < ilikeItemsList.size(); i++) {
+ ilikeItems[i] = ilikeItemsList.get(i).getItemName();
+ }
+ session.close();
+ return ilikeItems;
+ }
+
+ // To get records having itemPrice in between 100 and 200
+ public String[] betweenCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ // To get items having price more than 1000
+ criteriaItem.select(rootItem).where(builder.between(rootItem.get("itemPrice"), 100, 200));
+ final List
- betweenItemsList = session.createQuery(criteriaItem).getResultList();
+ final String betweenItems[] = new String[betweenItemsList.size()];
+ for (int i = 0; i < betweenItemsList.size(); i++) {
+ betweenItems[i] = betweenItemsList.get(i).getItemName();
+ }
+ session.close();
+ return betweenItems;
+ }
+
+ // To check if the given property is null
+ public String[] nullCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription")));
+ final List
- nullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String nullDescItems[] = new String[nullItemsList.size()];
+ for (int i = 0; i < nullItemsList.size(); i++) {
+ nullDescItems[i] = nullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return nullDescItems;
+ }
+
+ // To check if the given property is not null
+ public String[] notNullCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNotNull(rootItem.get("itemDescription")));
+ final List
- notNullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String notNullDescItems[] = new String[notNullItemsList.size()];
+ for (int i = 0; i < notNullItemsList.size(); i++) {
+ notNullDescItems[i] = notNullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return notNullDescItems;
+ }
+
+ // Adding more than one expression in one cr
+ public String[] twoCriteria() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription")))
+ .where(builder.like(rootItem.get("itemName"), "chair%"));
+ final List
- notNullItemsList = session.createQuery(criteriaItem).getResultList();
+ final String notNullDescItems[] = new String[notNullItemsList.size()];
+ for (int i = 0; i < notNullItemsList.size(); i++) {
+ notNullDescItems[i] = notNullItemsList.get(i).getItemName();
+ }
+ session.close();
+ return notNullDescItems;
+ }
+
+ // To get items matching with the above defined conditions joined
+ // with Logical AND
+ public String[] andLogicalCriteria() {
+ List predicates = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ predicates.add(builder.like(rootItem.get("itemName"), "Chair%"));
+ Predicate andPredicate = builder.and(predicates.toArray(new Predicate[] {}));
+ criteriaItem.select(rootItem).where(andPredicate);
+ final List
- andItemsList = session.createQuery(criteriaItem).getResultList();
+ final String andItems[] = new String[andItemsList.size()];
+ for (int i = 0; i < andItemsList.size(); i++) {
+ andItems[i] = andItemsList.get(i).getItemName();
+ }
+ session.close();
+ return andItems;
+ }
+
+ // To get items matching with the above defined conditions joined
+ // with Logical OR
+ public String[] orLogicalCriteria() {
+ List predicates = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ predicates.add(builder.greaterThan(rootItem.get("itemPrice"), 1000));
+ predicates.add(builder.like(rootItem.get("itemName"), "Chair%"));
+ Predicate orPredicate = builder.or(predicates.toArray(new Predicate[] {}));
+ criteriaItem.select(rootItem).where(orPredicate);
+ final List
- orItemsList = session.createQuery(criteriaItem).getResultList();
+ final String orItems[] = new String[orItemsList.size()];
+ for (int i = 0; i < orItemsList.size(); i++) {
+ orItems[i] = orItemsList.get(i).getItemName();
+ }
+ session.close();
+ return orItems;
+ }
+
+ // Sorting example
+ public String[] sortingCriteria() {
+ List listOrders = new ArrayList();
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery
- criteriaItem = builder.createQuery(Item.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ listOrders.add(builder.asc(rootItem.get("itemName")));
+ listOrders.add(builder.desc(rootItem.get("itemPrice")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List
- sortedItemsList = session.createQuery(criteriaItem).getResultList();
+ final String sortedItems[] = new String[sortedItemsList.size()];
+ for (int i = 0; i < sortedItemsList.size(); i++) {
+ sortedItems[i] = sortedItemsList.get(i).getItemName();
+ }
+ session.close();
+ return sortedItems;
+ }
+
+ // Set projections Row Count
+ public Long[] projectionRowCount() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.multiselect(builder.count(rootItem));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ final Long projectedRowCount[] = new Long[1];
+ projectedRowCount[0] = (long) itemProjected.get(0).get(0);
+ session.close();
+ return projectedRowCount;
+ }
+
+ // Set projections average of itemPrice
+ public Double[] projectionAverage() {
+ final Session session = HibernateUtil.getHibernateSession();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root
- rootItem = criteriaItem.from(Item.class);
+ criteriaItem.multiselect(builder.avg(rootItem.get("itemPrice")));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ Double avgItemPrice[] = new Double[1];
+ avgItemPrice[0] = Double.valueOf(itemProjected.get(0).get(0).toString());
+ session.close();
+ return avgItemPrice;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
new file mode 100644
index 0000000000..f4a9b8a678
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java
@@ -0,0 +1,58 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Date;
+
+@Entity
+@Table(name = "USER_ORDER")
+public class OrderDetail implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "ORDER_ID")
+ private Long orderId;
+
+ public OrderDetail() {
+ }
+
+ public OrderDetail(Date orderDate, String orderDesc) {
+ super();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((orderId == null) ? 0 : orderId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OrderDetail other = (OrderDetail) obj;
+ if (orderId == null) {
+ if (other.orderId != null)
+ return false;
+ } else if (!orderId.equals(other.orderId))
+ return false;
+
+ return true;
+ }
+
+ public Long getOrderId() {
+ return orderId;
+ }
+
+ public void setOrderId(Long orderId) {
+ this.orderId = orderId;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
new file mode 100644
index 0000000000..a1aa746399
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java
@@ -0,0 +1,71 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "USER")
+public class UserEager implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "USER_ID")
+ private Long userId;
+
+ @OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
+ private Set orderDetail = new HashSet();
+
+ public UserEager() {
+ }
+
+ public UserEager(final Long userId) {
+ super();
+ this.userId = userId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final UserEager other = (UserEager) obj;
+ if (userId == null) {
+ if (other.userId != null)
+ return false;
+ } else if (!userId.equals(other.userId))
+ return false;
+ return true;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(final Long userId) {
+ this.userId = userId;
+ }
+
+ public Set getOrderDetail() {
+ return orderDetail;
+ }
+
+ public void setOrderDetail(Set orderDetail) {
+ this.orderDetail = orderDetail;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
new file mode 100644
index 0000000000..e1354b5d24
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java
@@ -0,0 +1,71 @@
+package com.baeldung.hibernate.fetching.model;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+@Entity
+@Table(name = "USER")
+public class UserLazy implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue
+ @Column(name = "USER_ID")
+ private Long userId;
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
+ private Set orderDetail = new HashSet();
+
+ public UserLazy() {
+ }
+
+ public UserLazy(final Long userId) {
+ super();
+ this.userId = userId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final UserLazy other = (UserLazy) obj;
+ if (userId == null) {
+ if (other.userId != null)
+ return false;
+ } else if (!userId.equals(other.userId))
+ return false;
+ return true;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUserId(final Long userId) {
+ this.userId = userId;
+ }
+
+ public Set getOrderDetail() {
+ return orderDetail;
+ }
+
+ public void setOrderDetail(Set orderDetail) {
+ this.orderDetail = orderDetail;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java
new file mode 100644
index 0000000000..422de2ea93
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java
@@ -0,0 +1,28 @@
+package com.baeldung.hibernate.fetching.util;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+public class HibernateUtil {
+
+ public static Session getHibernateSession(String fetchMethod) {
+ // two config files are there
+ // one with lazy loading enabled
+ // another lazy = false
+ SessionFactory sf;
+ if ("lazy".equals(fetchMethod)) {
+ sf = new Configuration().configure("fetchingLazy.cfg.xml").buildSessionFactory();
+ } else {
+ sf = new Configuration().configure("fetching.cfg.xml").buildSessionFactory();
+ }
+
+ // fetching.cfg.xml is used for this example
+ return sf.openSession();
+ }
+
+ public static Session getHibernateSession() {
+ return new Configuration().configure("fetching.cfg.xml").buildSessionFactory().openSession();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java
new file mode 100644
index 0000000000..7fc543f693
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java
@@ -0,0 +1,68 @@
+package com.baeldung.hibernate.fetching.view;
+
+import com.baeldung.hibernate.fetching.model.OrderDetail;
+import com.baeldung.hibernate.fetching.model.UserEager;
+import com.baeldung.hibernate.fetching.model.UserLazy;
+import com.baeldung.hibernate.fetching.util.HibernateUtil;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+
+import java.util.List;
+import java.util.Set;
+
+public class FetchingAppView {
+
+ public FetchingAppView() {
+
+ }
+
+ // lazily loaded
+ public Set lazyLoaded() {
+ final Session sessionLazy = HibernateUtil.getHibernateSession("lazy");
+ List users = sessionLazy.createQuery("From UserLazy").getResultList();
+ UserLazy userLazyLoaded = users.get(3);
+ // since data is lazyloaded so data won't be initialized
+ return (userLazyLoaded.getOrderDetail());
+ }
+
+ // eagerly loaded
+ public Set eagerLoaded() {
+ final Session sessionEager = HibernateUtil.getHibernateSession();
+ // data should be loaded in the following line
+ // also note the queries generated
+ List user = sessionEager.createQuery("From UserEager").getResultList();
+ UserEager userEagerLoaded = user.get(3);
+ return userEagerLoaded.getOrderDetail();
+ }
+
+ // creates test data
+ // call this method to create the data in the database
+ public void createTestData() {
+
+ final Session session = HibernateUtil.getHibernateSession("lazy");
+ Transaction tx = session.beginTransaction();
+ final UserLazy user1 = new UserLazy();
+ final UserLazy user2 = new UserLazy();
+ final UserLazy user3 = new UserLazy();
+
+ session.save(user1);
+ session.save(user2);
+ session.save(user3);
+
+ final OrderDetail order1 = new OrderDetail();
+ final OrderDetail order2 = new OrderDetail();
+ final OrderDetail order3 = new OrderDetail();
+ final OrderDetail order4 = new OrderDetail();
+ final OrderDetail order5 = new OrderDetail();
+
+ session.saveOrUpdate(order1);
+ session.saveOrUpdate(order2);
+ session.saveOrUpdate(order3);
+ session.saveOrUpdate(order4);
+ session.saveOrUpdate(order5);
+
+ tx.commit();
+ session.close();
+
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java
new file mode 100644
index 0000000000..182b493592
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableDao extends IBarDao, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java
new file mode 100644
index 0000000000..4d7db64240
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java
@@ -0,0 +1,10 @@
+package com.baeldung.persistence.dao;
+
+import java.io.Serializable;
+
+import com.baeldung.persistence.model.Bar;
+import org.springframework.data.repository.CrudRepository;
+
+public interface IBarCrudRepository extends CrudRepository {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java
new file mode 100644
index 0000000000..7896a2a84a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IBarDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java
new file mode 100644
index 0000000000..a55a0b0598
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IChildDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IChildDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java
new file mode 100644
index 0000000000..ddbb685988
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableDao extends IFooDao, IAuditOperations {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java
new file mode 100644
index 0000000000..0935772dbd
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IFooDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IFooDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java
new file mode 100644
index 0000000000..03680158bb
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/IParentDao.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.dao;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IParentDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
new file mode 100644
index 0000000000..5a6c76a93a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractDao implements IOperations {
+
+ protected Class clazz;
+
+ protected final void setClazz(final Class clazzToSet) {
+ clazz = Preconditions.checkNotNull(clazzToSet);
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
new file mode 100644
index 0000000000..41184669ad
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
@@ -0,0 +1,37 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.envers.AuditReader;
+import org.hibernate.envers.AuditReaderFactory;
+import org.hibernate.envers.query.AuditQuery;
+
+@SuppressWarnings("unchecked")
+public class AbstractHibernateAuditableDao extends AbstractHibernateDao implements IAuditOperations {
+
+ @Override
+ public List getEntitiesAtRevision(final Number revision) {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forEntitiesAtRevision(clazz, revision);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+ @Override
+ public List getEntitiesModifiedAtRevision(final Number revision) {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forEntitiesModifiedAtRevision(clazz, revision);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+ @Override
+ public List getRevisions() {
+ final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession());
+ final AuditQuery query = auditReader.createQuery().forRevisionsOfEntity(clazz, true, true);
+ final List resultList = query.getResultList();
+ return resultList;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
new file mode 100644
index 0000000000..f34866d883
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java
@@ -0,0 +1,59 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.google.common.base.Preconditions;
+
+@SuppressWarnings("unchecked")
+public abstract class AbstractHibernateDao extends AbstractDao implements IOperations {
+
+ @Autowired
+ protected SessionFactory sessionFactory;
+
+ // API
+
+ @Override
+ public T findOne(final long id) {
+ return (T) getCurrentSession().get(clazz, id);
+ }
+
+ @Override
+ public List findAll() {
+ return getCurrentSession().createQuery("from " + clazz.getName()).getResultList();
+ }
+
+ @Override
+ public void create(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().saveOrUpdate(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ Preconditions.checkNotNull(entity);
+ return (T) getCurrentSession().merge(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ Preconditions.checkNotNull(entity);
+ getCurrentSession().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ final T entity = findOne(entityId);
+ Preconditions.checkState(entity != null);
+ delete(entity);
+ }
+
+ protected Session getCurrentSession() {
+ return sessionFactory.getCurrentSession();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
new file mode 100644
index 0000000000..69f8e58c25
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java
@@ -0,0 +1,56 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+public class AbstractJpaDao extends AbstractDao implements IOperations {
+
+ @PersistenceContext
+ private EntityManager em;
+
+ // API
+
+ @Override
+ public T findOne(final long id) {
+ return em.find(clazz, Long.valueOf(id).intValue());
+ }
+
+ @Override
+ public List findAll() {
+ final CriteriaBuilder cb = em.getCriteriaBuilder();
+ final CriteriaQuery cq = cb.createQuery(clazz);
+ final Root rootEntry = cq.from(clazz);
+ final CriteriaQuery all = cq.select(rootEntry);
+ final TypedQuery allQuery = em.createQuery(all);
+ return allQuery.getResultList();
+ }
+
+ @Override
+ public void create(final T entity) {
+ em.persist(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ em.merge(entity);
+ return entity;
+ }
+
+ @Override
+ public void delete(final T entity) {
+ em.remove(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ delete(findOne(entityId));
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
new file mode 100644
index 0000000000..18b16fa033
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java
@@ -0,0 +1,13 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Scope(BeanDefinition.SCOPE_PROTOTYPE)
+public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java
new file mode 100644
index 0000000000..169d3fed72
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IAuditOperations {
+
+ List getEntitiesAtRevision(Number revision);
+
+ List getEntitiesModifiedAtRevision(Number revision);
+
+ List getRevisions();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
new file mode 100644
index 0000000000..8d8af18394
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java
@@ -0,0 +1,7 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+
+public interface IGenericDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
new file mode 100644
index 0000000000..4ef99221ab
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/common/IOperations.java
@@ -0,0 +1,20 @@
+package com.baeldung.persistence.dao.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+public interface IOperations {
+
+ T findOne(final long id);
+
+ List findAll();
+
+ void create(final T entity);
+
+ T update(final T entity);
+
+ void delete(final T entity);
+
+ void deleteById(final long entityId);
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java
new file mode 100644
index 0000000000..e12b6ae2da
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.dao.impl;
+
+import java.util.List;
+
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import com.baeldung.persistence.model.Bar;
+
+public class BarAuditableDao extends AbstractHibernateAuditableDao implements IBarAuditableDao {
+
+ public BarAuditableDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+ @Override
+ public List getRevisions() {
+ final List resultList = super.getRevisions();
+ for (final Bar bar : resultList) {
+ bar.getFooSet().size(); // force FooSet initialization
+ }
+ return resultList;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java
new file mode 100644
index 0000000000..0ead802dc5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.model.Bar;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class BarDao extends AbstractHibernateDao implements IBarDao {
+
+ public BarDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java
new file mode 100644
index 0000000000..e0fa382d41
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.AbstractJpaDao;
+import com.baeldung.persistence.model.Bar;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class BarJpaDao extends AbstractJpaDao implements IBarDao {
+
+ public BarJpaDao() {
+ super();
+
+ setClazz(Bar.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java
new file mode 100644
index 0000000000..b55da6e43a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.IChildDao;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class ChildDao extends AbstractHibernateDao implements IChildDao {
+
+ public ChildDao() {
+ super();
+
+ setClazz(Child.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java
new file mode 100644
index 0000000000..05064c1478
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java
@@ -0,0 +1,17 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+
+public class FooAuditableDao extends AbstractHibernateAuditableDao implements IFooAuditableDao {
+
+ public FooAuditableDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
new file mode 100644
index 0000000000..787c449b1d
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.model.Foo;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class FooDao extends AbstractHibernateDao implements IFooDao {
+
+ public FooDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java
new file mode 100644
index 0000000000..4602b5f30e
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java
@@ -0,0 +1,19 @@
+package com.baeldung.persistence.dao.impl;
+
+import com.baeldung.persistence.dao.IParentDao;
+import com.baeldung.persistence.dao.common.AbstractHibernateDao;
+import com.baeldung.persistence.model.Parent;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class ParentDao extends AbstractHibernateDao implements IParentDao {
+
+ public ParentDao() {
+ super();
+
+ setClazz(Parent.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java
new file mode 100644
index 0000000000..c7f05254cc
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Bar.java
@@ -0,0 +1,242 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+
+import org.hibernate.annotations.OrderBy;
+import org.hibernate.envers.Audited;
+import org.jboss.logging.Logger;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import com.google.common.collect.Sets;
+
+@Entity
+@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b")
+@Audited
+@EntityListeners(AuditingEntityListener.class)
+public class Bar implements Serializable {
+
+ private static Logger logger = Logger.getLogger(Bar.class);
+
+ public enum OPERATION {
+ INSERT, UPDATE, DELETE;
+ private String value;
+
+ OPERATION() {
+ value = toString();
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public static OPERATION parse(final String value) {
+ OPERATION operation = null;
+ for (final OPERATION op : OPERATION.values()) {
+ if (op.getValue().equals(value)) {
+ operation = op;
+ break;
+ }
+ }
+ return operation;
+ }
+ };
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id")
+ private int id;
+
+ @Column(name = "name")
+ private String name;
+
+ @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ @OrderBy(clause = "NAME DESC")
+ // @NotAudited
+ private Set fooSet = Sets.newHashSet();
+
+ @Column(name = "operation")
+ private String operation;
+
+ @Column(name = "timestamp")
+ private long timestamp;
+
+ @Column(name = "created_date", updatable = false, nullable = false)
+ @CreatedDate
+ private long createdDate;
+
+ @Column(name = "modified_date")
+ @LastModifiedDate
+ private long modifiedDate;
+
+ @Column(name = "created_by")
+ @CreatedBy
+ private String createdBy;
+
+ @Column(name = "modified_by")
+ @LastModifiedBy
+ private String modifiedBy;
+
+ public Bar() {
+ super();
+ }
+
+ public Bar(final String name) {
+ super();
+
+ this.name = name;
+ }
+
+ // API
+
+ public Set getFooSet() {
+ return fooSet;
+ }
+
+ public void setFooSet(final Set fooSet) {
+ this.fooSet = fooSet;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(final int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public OPERATION getOperation() {
+ return OPERATION.parse(operation);
+ }
+
+ public void setOperation(final OPERATION operation) {
+ this.operation = operation.getValue();
+ }
+
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(final long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public long getCreatedDate() {
+ return createdDate;
+ }
+
+ public void setCreatedDate(final long createdDate) {
+ this.createdDate = createdDate;
+ }
+
+ public long getModifiedDate() {
+ return modifiedDate;
+ }
+
+ public void setModifiedDate(final long modifiedDate) {
+ this.modifiedDate = modifiedDate;
+ }
+
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ public void setCreatedBy(final String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ public String getModifiedBy() {
+ return modifiedBy;
+ }
+
+ public void setModifiedBy(final String modifiedBy) {
+ this.modifiedBy = modifiedBy;
+ }
+
+ public void setOperation(final String operation) {
+ this.operation = operation;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Bar other = (Bar) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Bar [name=").append(name).append("]");
+ return builder.toString();
+ }
+
+ @PrePersist
+ public void onPrePersist() {
+ logger.info("@PrePersist");
+ audit(OPERATION.INSERT);
+ }
+
+ @PreUpdate
+ public void onPreUpdate() {
+ logger.info("@PreUpdate");
+ audit(OPERATION.UPDATE);
+ }
+
+ @PreRemove
+ public void onPreRemove() {
+ logger.info("@PreRemove");
+ audit(OPERATION.DELETE);
+ }
+
+ private void audit(final OPERATION operation) {
+ setOperation(operation);
+ setTimestamp((new Date()).getTime());
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java
new file mode 100644
index 0000000000..19cfb2e237
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Child.java
@@ -0,0 +1,51 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Child implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @OneToOne(mappedBy = "child")
+ private Parent parent;
+
+ public Child() {
+ super();
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public Parent getParent() {
+ return parent;
+ }
+
+ public void setParent(final Parent parent) {
+ this.parent = parent;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Child [id=").append(id).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java
new file mode 100644
index 0000000000..d36a1e58cf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Foo.java
@@ -0,0 +1,105 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+
+import org.hibernate.envers.Audited;
+
+@NamedNativeQueries({ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class), @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) })
+@Entity
+@Audited
+// @Proxy(lazy = false)
+public class Foo implements Serializable {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id")
+ private long id;
+
+ @Column(name = "name")
+ private String name;
+
+ @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+ @JoinColumn(name = "BAR_ID")
+ private Bar bar = new Bar();
+
+ public Foo() {
+ super();
+ }
+
+ public Foo(final String name) {
+ super();
+ this.name = name;
+ }
+
+ //
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(final Bar bar) {
+ this.bar = bar;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java
new file mode 100644
index 0000000000..fa6948990b
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Parent.java
@@ -0,0 +1,60 @@
+package com.baeldung.persistence.model;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Parent implements Serializable {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH })
+ @JoinColumn(name = "child_fk")
+ private Child child;
+
+ public Parent() {
+ super();
+ }
+
+ public Parent(final Child child) {
+ super();
+
+ this.child = child;
+ }
+
+ // API
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ public Child getChild() {
+ return child;
+ }
+
+ public void setChild(final Child child) {
+ this.child = child;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Parent [id=").append(id).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java
new file mode 100644
index 0000000000..6a95a7acf5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/model/Person.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java
new file mode 100644
index 0000000000..33e5634d12
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableService extends IBarService, IAuditOperations {
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java
new file mode 100644
index 0000000000..21185b5990
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IBarService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+
+public interface IBarService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java
new file mode 100644
index 0000000000..afe67a70c2
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IChildService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IChildService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java
new file mode 100644
index 0000000000..b787e7fe91
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableService extends IFooService, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java
new file mode 100644
index 0000000000..ffdb53964a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IFooService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IFooService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java
new file mode 100644
index 0000000000..f941416aac
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/IParentService.java
@@ -0,0 +1,8 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.dao.common.IOperations;
+
+public interface IParentService extends IOperations {
+ //
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
new file mode 100644
index 0000000000..8e2df15519
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "hibernateTransactionManager")
+public abstract class AbstractHibernateAuditableService extends AbstractHibernateService
+ implements IOperations, IAuditOperations {
+
+ @Override
+ public List getEntitiesAtRevision(final Number revision) {
+ return getAuditableDao().getEntitiesAtRevision(revision);
+ }
+
+ @Override
+ public List getEntitiesModifiedAtRevision(final Number revision) {
+ return getAuditableDao().getEntitiesModifiedAtRevision(revision);
+ }
+
+ @Override
+ public List getRevisions() {
+ return getAuditableDao().getRevisions();
+ }
+
+ abstract protected IAuditOperations getAuditableDao();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java
new file mode 100644
index 0000000000..5da2f299f1
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java
@@ -0,0 +1,43 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "hibernateTransactionManager")
+public abstract class AbstractHibernateService extends AbstractService implements
+ IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return super.findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return super.findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ super.create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return super.update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ super.delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ super.deleteById(entityId);
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java
new file mode 100644
index 0000000000..a1c6fe9edf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java
@@ -0,0 +1,42 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional(value = "jpaTransactionManager")
+public abstract class AbstractJpaService extends AbstractService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return super.findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return super.findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ super.create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return super.update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ super.delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ super.deleteById(entityId);
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
new file mode 100644
index 0000000000..9b001b1fac
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractService.java
@@ -0,0 +1,42 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+
+public abstract class AbstractService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return getDao().findOne(id);
+ }
+
+ @Override
+ public List findAll() {
+ return getDao().findAll();
+ }
+
+ @Override
+ public void create(final T entity) {
+ getDao().create(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return getDao().update(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ getDao().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ getDao().deleteById(entityId);
+ }
+
+ protected abstract IOperations getDao();
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
new file mode 100644
index 0000000000..cef483e6bf
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
@@ -0,0 +1,46 @@
+package com.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.baeldung.persistence.dao.common.IOperations;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.google.common.collect.Lists;
+
+@Transactional(value = "jpaTransactionManager")
+public abstract class AbstractSpringDataJpaService implements IOperations {
+
+ @Override
+ public T findOne(final long id) {
+ return getDao().findOne(Long.valueOf(id));
+ }
+
+ @Override
+ public List findAll() {
+ return Lists.newArrayList(getDao().findAll());
+ }
+
+ @Override
+ public void create(final T entity) {
+ getDao().save(entity);
+ }
+
+ @Override
+ public T update(final T entity) {
+ return getDao().save(entity);
+ }
+
+ @Override
+ public void delete(final T entity) {
+ getDao().delete(entity);
+ }
+
+ @Override
+ public void deleteById(final long entityId) {
+ getDao().delete(Long.valueOf(entityId));
+ }
+
+ protected abstract CrudRepository getDao();
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java
new file mode 100644
index 0000000000..d84c28caa5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java
@@ -0,0 +1,41 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarAuditableService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarAuditableService extends AbstractHibernateAuditableService implements IBarAuditableService {
+
+ @Autowired
+ @Qualifier("barHibernateDao")
+ private IBarDao dao;
+
+ @Autowired
+ @Qualifier("barHibernateAuditableDao")
+ private IBarAuditableDao auditDao;
+
+ public BarAuditableService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+ @Override
+ protected IAuditOperations getAuditableDao() {
+ return auditDao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java
new file mode 100644
index 0000000000..1c1b7a2274
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.common.AbstractJpaService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarJpaService extends AbstractJpaService implements IBarService {
+
+ @Autowired
+ @Qualifier("barJpaDao")
+ private IBarDao dao;
+
+ public BarJpaService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java
new file mode 100644
index 0000000000..32d1f919c5
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class BarService extends AbstractHibernateService implements IBarService {
+
+ @Autowired
+ @Qualifier("barHibernateDao")
+ private IBarDao dao;
+
+ public BarService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java
new file mode 100644
index 0000000000..4a55d08a35
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java
@@ -0,0 +1,26 @@
+package com.baeldung.persistence.service.impl;
+
+import java.io.Serializable;
+
+import com.baeldung.persistence.service.common.AbstractSpringDataJpaService;
+import com.baeldung.persistence.dao.IBarCrudRepository;
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.repository.CrudRepository;
+
+public class BarSpringDataJpaService extends AbstractSpringDataJpaService implements IBarService {
+
+ @Autowired
+ private IBarCrudRepository dao;
+
+ public BarSpringDataJpaService() {
+ super();
+ }
+
+ @Override
+ protected CrudRepository getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java
new file mode 100644
index 0000000000..417fe2c49a
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ChildService.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.service.IChildService;
+import com.baeldung.persistence.dao.IChildDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ChildService extends AbstractHibernateService implements IChildService {
+
+ @Autowired
+ private IChildDao dao;
+
+ public ChildService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java
new file mode 100644
index 0000000000..45ad315c42
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java
@@ -0,0 +1,41 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.common.IAuditOperations;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FooAuditableService extends AbstractHibernateAuditableService implements IFooAuditableService {
+
+ @Autowired
+ @Qualifier("fooHibernateDao")
+ private IFooDao dao;
+
+ @Autowired
+ @Qualifier("fooHibernateAuditableDao")
+ private IFooAuditableDao auditDao;
+
+ public FooAuditableService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+ @Override
+ protected IAuditOperations getAuditableDao() {
+ return auditDao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java
new file mode 100644
index 0000000000..84cf018fee
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/FooService.java
@@ -0,0 +1,30 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+@Service
+public class FooService extends AbstractHibernateService implements IFooService {
+
+ @Autowired
+ @Qualifier("fooHibernateDao")
+ private IFooDao dao;
+
+ public FooService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java
new file mode 100644
index 0000000000..078acfc369
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/impl/ParentService.java
@@ -0,0 +1,28 @@
+package com.baeldung.persistence.service.impl;
+
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.persistence.service.IParentService;
+import com.baeldung.persistence.dao.IParentDao;
+import com.baeldung.persistence.dao.common.IOperations;
+import com.baeldung.persistence.service.common.AbstractHibernateService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ParentService extends AbstractHibernateService implements IParentService {
+
+ @Autowired
+ private IParentDao dao;
+
+ public ParentService() {
+ super();
+ }
+
+ // API
+
+ @Override
+ protected IOperations getDao() {
+ return dao;
+ }
+
+}
diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java
new file mode 100644
index 0000000000..67ab97e516
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceConfig.java
@@ -0,0 +1,173 @@
+package com.baeldung.spring;
+
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
+import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.orm.hibernate5.HibernateTransactionManager;
+import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import com.baeldung.persistence.dao.IBarAuditableDao;
+import com.baeldung.persistence.dao.IBarDao;
+import com.baeldung.persistence.dao.IFooAuditableDao;
+import com.baeldung.persistence.dao.IFooDao;
+import com.baeldung.persistence.dao.impl.BarAuditableDao;
+import com.baeldung.persistence.dao.impl.BarDao;
+import com.baeldung.persistence.dao.impl.BarJpaDao;
+import com.baeldung.persistence.dao.impl.FooAuditableDao;
+import com.baeldung.persistence.dao.impl.FooDao;
+import com.baeldung.persistence.service.IBarAuditableService;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.persistence.service.impl.BarAuditableService;
+import com.baeldung.persistence.service.impl.BarJpaService;
+import com.baeldung.persistence.service.impl.BarSpringDataJpaService;
+import com.baeldung.persistence.service.impl.FooAuditableService;
+import com.baeldung.persistence.service.impl.FooService;
+import com.google.common.base.Preconditions;
+
+@Configuration
+@EnableTransactionManagement
+@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager")
+@EnableJpaAuditing
+@PropertySource({ "classpath:persistence-mysql.properties" })
+@ComponentScan({ "com.baeldung.persistence" })
+public class PersistenceConfig {
+
+ @Autowired
+ private Environment env;
+
+ @Bean
+ public LocalSessionFactoryBean sessionFactory() {
+ final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
+ sessionFactory.setDataSource(restDataSource());
+ sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+ sessionFactory.setHibernateProperties(hibernateProperties());
+
+ return sessionFactory;
+ }
+
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
+ emf.setDataSource(restDataSource());
+ emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+
+ final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
+ emf.setJpaVendorAdapter(vendorAdapter);
+ emf.setJpaProperties(hibernateProperties());
+
+ return emf;
+ }
+
+ @Bean
+ public DataSource restDataSource() {
+ final BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
+ dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
+ dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
+ dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
+
+ return dataSource;
+ }
+
+ @Bean
+ public PlatformTransactionManager hibernateTransactionManager() {
+ final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
+ transactionManager.setSessionFactory(sessionFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PlatformTransactionManager jpaTransactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+ return transactionManager;
+ }
+
+ @Bean
+ public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+ return new PersistenceExceptionTranslationPostProcessor();
+ }
+
+ @Bean
+ public IBarService barJpaService() {
+ return new BarJpaService();
+ }
+
+ @Bean
+ public IBarService barSpringDataJpaService() {
+ return new BarSpringDataJpaService();
+ }
+
+ @Bean
+ public IFooService fooHibernateService() {
+ return new FooService();
+ }
+
+ @Bean
+ public IBarAuditableService barHibernateAuditableService() {
+ return new BarAuditableService();
+ }
+
+ @Bean
+ public IFooAuditableService fooHibernateAuditableService() {
+ return new FooAuditableService();
+ }
+
+ @Bean
+ public IBarDao barJpaDao() {
+ return new BarJpaDao();
+ }
+
+ @Bean
+ public IBarDao barHibernateDao() {
+ return new BarDao();
+ }
+
+ @Bean
+ public IBarAuditableDao barHibernateAuditableDao() {
+ return new BarAuditableDao();
+ }
+
+ @Bean
+ public IFooDao fooHibernateDao() {
+ return new FooDao();
+ }
+
+ @Bean
+ public IFooAuditableDao fooHibernateAuditableDao() {
+ return new FooAuditableDao();
+ }
+
+ private final Properties hibernateProperties() {
+ final Properties hibernateProperties = new Properties();
+ hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
+ hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
+
+ hibernateProperties.setProperty("hibernate.show_sql", "true");
+
+ // Envers properties
+ hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
+
+ return hibernateProperties;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java
new file mode 100644
index 0000000000..e93fcca3e1
--- /dev/null
+++ b/spring-hibernate5/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java
@@ -0,0 +1,14 @@
+package com.baeldung.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@Configuration
+@EnableTransactionManagement
+@ComponentScan({ "com.baeldung.persistence.dao", "com.baeldung.persistence.service" })
+@ImportResource({ "classpath:hibernate5Config.xml" })
+public class PersistenceXmlConfig {
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/criteria.cfg.xml b/spring-hibernate5/src/main/resources/criteria.cfg.xml
new file mode 100644
index 0000000000..0b865fc4d1
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/criteria.cfg.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/criteria_create_queries.sql b/spring-hibernate5/src/main/resources/criteria_create_queries.sql
new file mode 100644
index 0000000000..3a627dd38c
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/criteria_create_queries.sql
@@ -0,0 +1,7 @@
+CREATE TABLE `item` (
+ `ITEM_ID` int(11) NOT NULL AUTO_INCREMENT,
+ `ITEM_DESC` varchar(100) DEFAULT NULL,
+ `ITEM_PRICE` int(11) NOT NULL,
+ `ITEM_NAME` varchar(255) NOT NULL,
+ PRIMARY KEY (`ITEM_ID`)
+) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
diff --git a/spring-hibernate5/src/main/resources/fetching.cfg.xml b/spring-hibernate5/src/main/resources/fetching.cfg.xml
new file mode 100644
index 0000000000..b1ffecafce
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetching.cfg.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+ validate
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml
new file mode 100644
index 0000000000..a18fdbfa99
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetchingLazy.cfg.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/fetching_create_queries.sql b/spring-hibernate5/src/main/resources/fetching_create_queries.sql
new file mode 100644
index 0000000000..b36d9828f1
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/fetching_create_queries.sql
@@ -0,0 +1,14 @@
+CREATE TABLE `user` (
+ `user_id` int(10) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1 ;
+
+
+CREATE TABLE `user_order` (
+ `ORDER_ID` int(10) NOT NULL AUTO_INCREMENT,
+ `USER_ID` int(10) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ORDER_ID`,`USER_ID`),
+ KEY `USER_ID` (`USER_ID`),
+ CONSTRAINT `user_order_ibfk_1` FOREIGN KEY (`USER_ID`) REFERENCES `USER` (`user_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
+
diff --git a/spring-hibernate5/src/main/resources/hibernate5Config.xml b/spring-hibernate5/src/main/resources/hibernate5Config.xml
new file mode 100644
index 0000000000..55546a862a
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/hibernate5Config.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+ ${hibernate.hbm2ddl.auto}
+ ${hibernate.dialect}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/insert_statements.sql b/spring-hibernate5/src/main/resources/insert_statements.sql
new file mode 100644
index 0000000000..ae008f29bc
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/insert_statements.sql
@@ -0,0 +1,31 @@
+insert into item (item_id, item_name, item_desc, item_price)
+values(1,'item One', 'test 1', 35.12);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(2,'Pogo stick', 'Pogo stick', 466.12);
+insert into item (item_id, item_name, item_desc, item_price)
+values(3,'Raft', 'Raft', 345.12);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(4,'Skate Board', 'Skating', 135.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(5,'Umbrella', 'Umbrella for Rain', 619.25);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(6,'Glue', 'Glue for home', 432.73);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(7,'Paint', 'Paint for Room', 1311.40);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(8,'Red paint', 'Red paint for room', 1135.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(9,'Household Chairs', 'Chairs for house', 25.71);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(10,'Office Chairs', 'Chairs for office', 395.98);
+
+insert into item (item_id, item_name, item_desc, item_price)
+values(11,'Outdoor Chairs', 'Chairs for outdoor activities', 1234.36);
diff --git a/spring-hibernate5/src/main/resources/logback.xml b/spring-hibernate5/src/main/resources/logback.xml
new file mode 100644
index 0000000000..71a6d50a58
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/logback.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ web - %date [%thread] %-5level %logger{36} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/persistence-mysql.properties b/spring-hibernate5/src/main/resources/persistence-mysql.properties
new file mode 100644
index 0000000000..1180929b30
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/persistence-mysql.properties
@@ -0,0 +1,13 @@
+# jdbc.X
+jdbc.driverClassName=com.mysql.cj.jdbc.Driver
+jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate5_01?createDatabaseIfNotExist=true
+jdbc.user=tutorialuser
+jdbc.pass=tutorialmy5ql
+
+# hibernate.X
+hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
+hibernate.show_sql=false
+hibernate.hbm2ddl.auto=create-drop
+
+# envers.X
+envers.audit_table_suffix=_audit_log
diff --git a/spring-hibernate5/src/main/resources/stored_procedure.sql b/spring-hibernate5/src/main/resources/stored_procedure.sql
new file mode 100644
index 0000000000..9cedb75c37
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/stored_procedure.sql
@@ -0,0 +1,20 @@
+DELIMITER //
+ CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo WHERE name = fooName;
+ END //
+DELIMITER ;
+
+
+DELIMITER //
+ CREATE PROCEDURE GetAllFoos()
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo;
+ END //
+DELIMITER ;
\ No newline at end of file
diff --git a/spring-hibernate5/src/main/resources/webSecurityConfig.xml b/spring-hibernate5/src/main/resources/webSecurityConfig.xml
new file mode 100644
index 0000000000..e5c19a4ad7
--- /dev/null
+++ b/spring-hibernate5/src/main/resources/webSecurityConfig.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
new file mode 100644
index 0000000000..7caa02f156
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java
@@ -0,0 +1,194 @@
+package com.baeldung.hibernate.criteria;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.hibernate.Session;
+import org.junit.Test;
+
+import com.baeldung.hibernate.criteria.model.Item;
+import com.baeldung.hibernate.criteria.util.HibernateUtil;
+import com.baeldung.hibernate.criteria.view.ApplicationView;
+
+public class HibernateCriteriaIntegrationTest {
+
+ final private ApplicationView av = new ApplicationView();
+
+ @Test
+ public void testPerformanceOfCriteria() {
+ assertTrue(av.checkIfCriteriaTimeLower());
+ }
+
+ @Test
+ public void testLikeCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedLikeList = session.createQuery("From Item where itemName like '%chair%'")
+ .getResultList();
+ final String expectedLikeItems[] = new String[expectedLikeList.size()];
+ for (int i = 0; i < expectedLikeList.size(); i++) {
+ expectedLikeItems[i] = expectedLikeList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedLikeItems, av.likeCriteria());
+ }
+
+ @Test
+ public void testILikeCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'")
+ .getResultList();
+ final String expectedChairCaseItems[] = new String[expectedChairCaseList.size()];
+ for (int i = 0; i < expectedChairCaseList.size(); i++) {
+ expectedChairCaseItems[i] = expectedChairCaseList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedChairCaseItems, av.likeCaseCriteria());
+
+ }
+
+ @Test
+ public void testNullCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null")
+ .getResultList();
+ final String expectedIsNullDescItems[] = new String[expectedIsNullDescItemsList.size()];
+ for (int i = 0; i < expectedIsNullDescItemsList.size(); i++) {
+ expectedIsNullDescItems[i] = expectedIsNullDescItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedIsNullDescItems, av.nullCriteria());
+ }
+
+ @Test
+ public void testIsNotNullCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedIsNotNullDescItemsList = session.createQuery(
+ "From Item where itemDescription is not null").getResultList();
+ final String expectedIsNotNullDescItems[] = new String[expectedIsNotNullDescItemsList.size()];
+ for (int i = 0; i < expectedIsNotNullDescItemsList.size(); i++) {
+ expectedIsNotNullDescItems[i] = expectedIsNotNullDescItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedIsNotNullDescItems, av.notNullCriteria());
+
+ }
+
+ @Test
+ public void testAverageProjection() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item")
+ .getResultList();
+
+ final Double expectedAvgProjItems[] = new Double[expectedAvgProjItemsList.size()];
+ for (int i = 0; i < expectedAvgProjItemsList.size(); i++) {
+ expectedAvgProjItems[i] = expectedAvgProjItemsList.get(i);
+ }
+ session.close();
+ assertArrayEquals(expectedAvgProjItems, av.projectionAverage());
+
+ }
+
+ @Test
+ public void testRowCountProjection() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List expectedCountProjItemsList = session.createQuery("Select count(*) from Item").getResultList();
+ final Long expectedCountProjItems[] = new Long[expectedCountProjItemsList.size()];
+ for (int i = 0; i < expectedCountProjItemsList.size(); i++) {
+ expectedCountProjItems[i] = expectedCountProjItemsList.get(i);
+ }
+ session.close();
+ assertArrayEquals(expectedCountProjItems, av.projectionRowCount());
+ }
+
+ @Test
+ public void testOrCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedOrCritItemsList = session.createQuery(
+ "From Item where itemPrice>1000 or itemName like 'Chair%'").getResultList();
+ final String expectedOrCritItems[] = new String[expectedOrCritItemsList.size()];
+ for (int i = 0; i < expectedOrCritItemsList.size(); i++) {
+ expectedOrCritItems[i] = expectedOrCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedOrCritItems, av.orLogicalCriteria());
+ }
+
+ @Test
+ public void testAndCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedAndCritItemsList = session.createQuery(
+ "From Item where itemPrice>1000 and itemName like 'Chair%'").getResultList();
+ final String expectedAndCritItems[] = new String[expectedAndCritItemsList.size()];
+ for (int i = 0; i < expectedAndCritItemsList.size(); i++) {
+ expectedAndCritItems[i] = expectedAndCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedAndCritItems, av.andLogicalCriteria());
+ }
+
+ @Test
+ public void testMultiCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedMultiCritItemsList = session.createQuery(
+ "From Item where itemDescription is null and itemName like'chair%'").getResultList();
+ final String expectedMultiCritItems[] = new String[expectedMultiCritItemsList.size()];
+ for (int i = 0; i < expectedMultiCritItemsList.size(); i++) {
+ expectedMultiCritItems[i] = expectedMultiCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedMultiCritItems, av.twoCriteria());
+ }
+
+ @Test
+ public void testSortCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedSortCritItemsList = session.createQuery(
+ "From Item order by itemName asc, itemPrice desc").getResultList();
+ final String expectedSortCritItems[] = new String[expectedSortCritItemsList.size()];
+ for (int i = 0; i < expectedSortCritItemsList.size(); i++) {
+ expectedSortCritItems[i] = expectedSortCritItemsList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedSortCritItems, av.sortingCriteria());
+ }
+
+ @Test
+ public void testGreaterThanCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000")
+ .getResultList();
+ final String expectedGreaterThanItems[] = new String[expectedGreaterThanList.size()];
+ for (int i = 0; i < expectedGreaterThanList.size(); i++) {
+ expectedGreaterThanItems[i] = expectedGreaterThanList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedGreaterThanItems, av.greaterThanCriteria());
+ }
+
+ @Test
+ public void testLessThanCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedLessList = session.createQuery("From Item where itemPrice<1000").getResultList();
+ final String expectedLessThanItems[] = new String[expectedLessList.size()];
+ for (int i = 0; i < expectedLessList.size(); i++) {
+ expectedLessThanItems[i] = expectedLessList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedLessThanItems, av.lessThanCriteria());
+ }
+
+ @Test
+ public void betweenCriteriaQuery() {
+ final Session session = HibernateUtil.getHibernateSession();
+ final List
- expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200")
+ .getResultList();
+ final String expectedPriceBetweenItems[] = new String[expectedBetweenList.size()];
+ for (int i = 0; i < expectedBetweenList.size(); i++) {
+ expectedPriceBetweenItems[i] = expectedBetweenList.get(i).getItemName();
+ }
+ session.close();
+ assertArrayEquals(expectedPriceBetweenItems, av.betweenCriteria());
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java
new file mode 100644
index 0000000000..99164efb7a
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java
@@ -0,0 +1,15 @@
+package com.baeldung.hibernate.criteria;
+
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+public class HibernateCriteriaTestRunner {
+
+ public static void main(final String[] args) {
+ Result result = JUnitCore.runClasses(HibernateCriteriaTestSuite.class);
+ for (Failure failure : result.getFailures()) {
+
+ }
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java
new file mode 100644
index 0000000000..dc1040734f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java
@@ -0,0 +1,11 @@
+package com.baeldung.hibernate.criteria;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ HibernateCriteriaIntegrationTest.class })
+
+public class HibernateCriteriaTestSuite {
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java
new file mode 100644
index 0000000000..65bf36f8bf
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java
@@ -0,0 +1,42 @@
+package com.baeldung.hibernate.fetching;
+
+import com.baeldung.hibernate.fetching.model.OrderDetail;
+import com.baeldung.hibernate.fetching.view.FetchingAppView;
+import org.hibernate.Hibernate;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Set;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class HibernateFetchingIntegrationTest {
+
+ // this loads sample data in the database
+ @Before
+ public void addFecthingTestData() {
+ FetchingAppView fav = new FetchingAppView();
+ fav.createTestData();
+ }
+
+ // testLazyFetching() tests the lazy loading
+ // Since it lazily loaded so orderDetalSetLazy won't
+ // be initialized
+ @Test
+ public void testLazyFetching() {
+ FetchingAppView fav = new FetchingAppView();
+ Set orderDetalSetLazy = fav.lazyLoaded();
+ assertFalse(Hibernate.isInitialized(orderDetalSetLazy));
+ }
+
+ // testEagerFetching() tests the eager loading
+ // Since it eagerly loaded so orderDetalSetLazy would
+ // be initialized
+ @Test
+ public void testEagerFetching() {
+ FetchingAppView fav = new FetchingAppView();
+ Set orderDetalSetEager = fav.eagerLoaded();
+ assertTrue(Hibernate.isInitialized(orderDetalSetEager));
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java
new file mode 100644
index 0000000000..f5c45a5d6f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java
@@ -0,0 +1,25 @@
+package com.baeldung.persistence;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import com.baeldung.persistence.audit.AuditTestSuite;
+import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest;
+import com.baeldung.persistence.hibernate.FooSortingPersistenceIntegrationTest;
+import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest;
+import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest;
+import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ // @formatter:off
+ AuditTestSuite.class
+ ,FooServiceBasicPersistenceIntegrationTest.class
+ ,FooPaginationPersistenceIntegrationTest.class
+ ,FooServicePersistenceIntegrationTest.class
+ ,ParentServicePersistenceIntegrationTest.class
+ ,FooSortingPersistenceIntegrationTest.class
+
+}) // @formatter:on
+public class IntegrationTestSuite {
+ //
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java
new file mode 100644
index 0000000000..34c725d62b
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java
@@ -0,0 +1,14 @@
+package com.baeldung.persistence.audit;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ // @formatter:off
+ EnversFooBarAuditIntegrationTest.class,
+ JPABarAuditIntegrationTest.class,
+ SpringDataJPABarAuditIntegrationTest.class
+}) // @formatter:on
+public class AuditTestSuite {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java
new file mode 100644
index 0000000000..ed2e111c8f
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java
@@ -0,0 +1,142 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IBarAuditableService;
+import com.baeldung.persistence.service.IFooAuditableService;
+import com.baeldung.spring.PersistenceConfig;
+import com.baeldung.persistence.model.Bar;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class EnversFooBarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("fooHibernateAuditableService")
+ private IFooAuditableService fooService;
+
+ @Autowired
+ @Qualifier("barHibernateAuditableService")
+ private IBarAuditableService barService;
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ makeRevisions();
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ session.close();
+ }
+
+ private void makeRevisions() {
+ final Bar bar = rev1();
+ rev2(bar);
+ rev3(bar);
+ rev4(bar);
+ }
+
+ // REV #1: insert BAR & FOO1
+ private Bar rev1() {
+ final Bar bar = new Bar("BAR");
+ final Foo foo1 = new Foo("FOO1");
+ foo1.setBar(bar);
+ fooService.create(foo1);
+ return bar;
+ }
+
+ // REV #2: insert FOO2 & update BAR
+ private void rev2(final Bar bar) {
+ final Foo foo2 = new Foo("FOO2");
+ foo2.setBar(bar);
+ fooService.create(foo2);
+ }
+
+ // REV #3: update BAR
+ private void rev3(final Bar bar) {
+
+ bar.setName("BAR1");
+ barService.update(bar);
+ }
+
+ // REV #4: insert FOO3 & update BAR
+ private void rev4(final Bar bar) {
+
+ final Foo foo3 = new Foo("FOO3");
+ foo3.setBar(bar);
+ fooService.create(foo3);
+ }
+
+ @Test
+ public final void whenFooBarsModified_thenFooBarsAudited() {
+
+ List barRevisionList;
+ List fooRevisionList;
+
+ // test Bar revisions
+
+ barRevisionList = barService.getRevisions();
+
+ assertNotNull(barRevisionList);
+ assertEquals(4, barRevisionList.size());
+
+ assertEquals("BAR", barRevisionList.get(0).getName());
+ assertEquals("BAR", barRevisionList.get(1).getName());
+ assertEquals("BAR1", barRevisionList.get(2).getName());
+ assertEquals("BAR1", barRevisionList.get(3).getName());
+
+ assertEquals(1, barRevisionList.get(0).getFooSet().size());
+ assertEquals(2, barRevisionList.get(1).getFooSet().size());
+ assertEquals(2, barRevisionList.get(2).getFooSet().size());
+ assertEquals(3, barRevisionList.get(3).getFooSet().size());
+
+ // test Foo revisions
+
+ fooRevisionList = fooService.getRevisions();
+ assertNotNull(fooRevisionList);
+ assertEquals(3, fooRevisionList.size());
+ assertEquals("FOO1", fooRevisionList.get(0).getName());
+ assertEquals("FOO2", fooRevisionList.get(1).getName());
+ assertEquals("FOO3", fooRevisionList.get(2).getName());
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
new file mode 100644
index 0000000000..b63a4b989b
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java
@@ -0,0 +1,102 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.model.Bar.OPERATION;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class JPABarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(JPABarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("barJpaService")
+ private IBarService barService;
+
+ @Autowired
+ private EntityManagerFactory entityManagerFactory;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ em = entityManagerFactory.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ em.close();
+ }
+
+ @Test
+ public final void whenBarsModified_thenBarsAudited() {
+
+ // insert BAR1
+ Bar bar1 = new Bar("BAR1");
+ barService.create(bar1);
+
+ // update BAR1
+ bar1.setName("BAR1a");
+ barService.update(bar1);
+
+ // insert BAR2
+ Bar bar2 = new Bar("BAR2");
+ barService.create(bar2);
+
+ // update BAR1
+ bar1.setName("BAR1b");
+ barService.update(bar1);
+
+ // get BAR1 and BAR2 from the DB and check the audit values
+ // detach instances from persistence context to make sure we fire db
+ em.detach(bar1);
+ em.detach(bar2);
+ bar1 = barService.findOne(bar1.getId());
+ bar2 = barService.findOne(bar2.getId());
+
+ assertNotNull(bar1);
+ assertNotNull(bar2);
+ assertEquals(OPERATION.UPDATE, bar1.getOperation());
+ assertEquals(OPERATION.INSERT, bar2.getOperation());
+ assertTrue(bar1.getTimestamp() > bar2.getTimestamp());
+
+ barService.deleteById(bar1.getId());
+ barService.deleteById(bar2.getId());
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
new file mode 100644
index 0000000000..e794b282f6
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.service.IBarService;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class SpringDataJPABarAuditIntegrationTest {
+
+ private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditIntegrationTest.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ logger.info("setUpBeforeClass()");
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ logger.info("tearDownAfterClass()");
+ }
+
+ @Autowired
+ @Qualifier("barSpringDataJpaService")
+ private IBarService barService;
+
+ @Autowired
+ private EntityManagerFactory entityManagerFactory;
+
+ private EntityManager em;
+
+ @Before
+ public void setUp() throws Exception {
+ logger.info("setUp()");
+ em = entityManagerFactory.createEntityManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logger.info("tearDown()");
+ em.close();
+ }
+
+ @Test
+ @WithMockUser(username = "tutorialuser")
+ public final void whenBarsModified_thenBarsAudited() {
+ Bar bar = new Bar("BAR1");
+ barService.create(bar);
+ assertEquals(bar.getCreatedDate(), bar.getModifiedDate());
+ assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy());
+ bar.setName("BAR2");
+ bar = barService.update(bar);
+ assertTrue(bar.getCreatedDate() < bar.getModifiedDate());
+ assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy());
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
new file mode 100644
index 0000000000..da840dc027
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java
@@ -0,0 +1,101 @@
+package com.baeldung.persistence.hibernate;
+
+import java.util.List;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.model.Bar;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+
+import com.google.common.collect.Lists;
+
+public class FooFixtures {
+ private SessionFactory sessionFactory;
+
+ public FooFixtures(final SessionFactory sessionFactory) {
+ super();
+
+ this.sessionFactory = sessionFactory;
+ }
+
+ // API
+
+ public void createBars() {
+ Session session = null;
+ Transaction tx = null;
+ session = sessionFactory.openSession();
+ tx = session.getTransaction();
+ try {
+ tx.begin();
+ for (int i = 156; i < 160; i++) {
+ final Bar bar = new Bar();
+ bar.setName("Bar_" + i);
+ final Foo foo = new Foo("Foo_" + (i + 120));
+ foo.setBar(bar);
+ session.save(foo);
+ final Foo foo2 = new Foo(null);
+ if (i % 2 == 0)
+ foo2.setName("LuckyFoo" + (i + 120));
+ foo2.setBar(bar);
+ session.save(foo2);
+ bar.getFooSet().add(foo);
+ bar.getFooSet().add(foo2);
+ session.merge(bar);
+ }
+ tx.commit();
+ session.flush();
+ } catch (final HibernateException he) {
+ if (tx != null)
+ tx.rollback();
+ System.out.println("Not able to open session");
+ he.printStackTrace();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (session != null)
+ session.close();
+ }
+
+ }
+
+ public void createFoos() {
+ Session session = null;
+ Transaction tx = null;
+ session = sessionFactory.openSession();
+ tx = session.getTransaction();
+ final List fooList = Lists.newArrayList();
+ for (int i = 35; i < 46; i++) {
+
+ final Foo foo = new Foo();
+ foo.setName("Foo_" + (i + 120));
+ final Bar bar = new Bar("bar_" + i);
+ bar.getFooSet().add(foo);
+ foo.setBar(bar);
+ fooList.add(foo);
+
+ }
+ try {
+ tx.begin();
+ for (final Foo foo : fooList) {
+
+ session.save(foo.getBar());
+ session.save(foo);
+ }
+ tx.commit();
+ session.flush();
+ } catch (final HibernateException he) {
+ if (tx != null)
+ tx.rollback();
+ System.out.println("Not able to open session");
+ he.printStackTrace();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (session != null)
+ session.close();
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..c9152b4d85
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java
@@ -0,0 +1,185 @@
+package com.baeldung.persistence.hibernate;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import javax.persistence.Tuple;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.ScrollMode;
+import org.hibernate.ScrollableResults;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+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.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.persistence.service.IFooService;
+import com.baeldung.spring.PersistenceConfig;
+import com.google.common.collect.Lists;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooPaginationPersistenceIntegrationTest {
+
+ @Autowired
+ private IFooService fooService;
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ // tests
+
+ @Before
+ public final void before() {
+ final int minimalNumberOfEntities = 25;
+ if (fooService.findAll().size() <= minimalNumberOfEntities) {
+ for (int i = 0; i < minimalNumberOfEntities; i++) {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+ }
+
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingPaginatedEntities_thenCorrectSize() {
+ final int pageNumber = 1;
+ final int pageSize = 10;
+ final List fooList = session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList();
+ assertThat(fooList, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingAllPages_thenCorrect() {
+ int pageNumber = 1;
+ final int pageSize = 10;
+
+ final String countQ = "Select count (f.id) from Foo f";
+ final Long countResult = (Long) session.createQuery(countQ).uniqueResult();
+
+ final List fooList = Lists.newArrayList();
+ int totalEntities = 0;
+ while (totalEntities < countResult) {
+ fooList.addAll(session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList());
+ totalEntities = fooList.size();
+ pageNumber++;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void whenRetrievingLastPage_thenCorrectSize() {
+ final int pageSize = 10;
+
+ final String countQ = "Select count (f.id) from Foo f";
+ final Long countResults = (Long) session.createQuery(countQ).uniqueResult();
+ final int lastPageNumber = (int) ((countResults / pageSize) + 1);
+
+ final List lastPage = session.createQuery("From Foo").setFirstResult((lastPageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList();
+
+ assertThat(lastPage, hasSize(lessThan(pageSize + 1)));
+ }
+
+ // testing - scrollable
+
+ @Test
+ public final void givenUsingTheScrollableApi_whenRetrievingPaginatedData_thenCorrect() {
+ final int pageSize = 10;
+ final String hql = "FROM Foo f order by f.name";
+
+ final ScrollableResults resultScroll = session.createQuery(hql).scroll(ScrollMode.FORWARD_ONLY);
+
+ // resultScroll.last();
+ // final int totalResults = resultScroll.getRowNumber() + 1;
+
+ resultScroll.first();
+ resultScroll.scroll(0);
+ final List fooPage = Lists.newArrayList();
+ int i = 0;
+ while (pageSize > i++) {
+ fooPage.add((Foo) resultScroll.get(0));
+ if (!resultScroll.next()) {
+ break;
+ }
+ }
+
+ assertThat(fooPage, hasSize(lessThan(10 + 1)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenUsingTheCriteriaApi_whenRetrievingFirstPage_thenCorrect() {
+ final int pageSize = 10;
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ criteriaItem.select(rootItem);
+ final List firstPage = session.createQuery(criteriaItem).setFirstResult(0).setMaxResults(pageSize)
+ .getResultList();
+
+ assertThat(firstPage, hasSize(pageSize));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public final void givenUsingTheCriteriaApi_whenRetrievingPaginatedData_thenCorrect() {
+
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Tuple.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ criteriaItem.multiselect(builder.count(rootItem));
+ final List itemProjected = session.createQuery(criteriaItem).getResultList();
+ final Long count = (Long) itemProjected.get(0).get(0);
+
+ int pageNumber = 1;
+ final int pageSize = 10;
+ final List fooList = Lists.newArrayList();
+
+ CriteriaBuilder builderFoo = session.getCriteriaBuilder();
+ CriteriaQuery criteriaFoo = builderFoo.createQuery(Foo.class);
+ Root rootFoo = criteriaFoo.from(Foo.class);
+ criteriaFoo.select(rootFoo);
+
+ int totalEntities = 0;
+ while (totalEntities < count.intValue()) {
+ fooList.addAll(session.createQuery(criteriaFoo).setFirstResult((pageNumber - 1) * pageSize)
+ .setMaxResults(pageSize).getResultList());
+ totalEntities = fooList.size();
+ pageNumber++;
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..813fb65641
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java
@@ -0,0 +1,179 @@
+package com.baeldung.persistence.hibernate;
+
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.Criteria;
+import org.hibernate.NullPrecedence;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+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.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Bar;
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+@SuppressWarnings("unchecked")
+public class FooSortingPersistenceIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ private Session session;
+
+ @Before
+ public void before() {
+ session = sessionFactory.openSession();
+
+ session.beginTransaction();
+
+ final FooFixtures fooData = new FooFixtures(sessionFactory);
+ fooData.createBars();
+ }
+
+ @After
+ public void after() {
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ @Test
+ public final void whenHQlSortingByOneAttribute_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByStringNullLast_thenLastNull() {
+ final String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
+ final List fooList = session.createQuery(hql).getResultList();
+
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenSortingByStringNullsFirst_thenReturnNullsFirst() {
+ final String hql = "FROM Foo f ORDER BY f.name NULLS FIRST";
+ final List fooList = session.createQuery(hql).getResultList();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Name:" + foo.getName());
+
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByOneAttribute_andOrderDirection_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name ASC";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByMultipleAttributes_thenSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name, f.id";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQlSortingByMultipleAttributes_andOrderDirection_thenPrintSortedResults() {
+ final String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
+ final List fooList = session.createQuery(hql).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Name: " + foo.getName() + ", Id: " + foo.getId());
+ }
+ }
+
+ @Test
+ public final void whenHQLCriteriaSortingByOneAttr_thenPrintSortedResults() {
+ List listOrders = new ArrayList();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ listOrders.add(builder.asc(rootItem.get("id")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List fooList = session.createQuery(criteriaItem).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ @Test
+ public final void whenHQLCriteriaSortingByMultipAttr_thenSortedResults() {
+ List listOrders = new ArrayList();
+ CriteriaBuilder builder = session.getCriteriaBuilder();
+ CriteriaQuery criteriaItem = builder.createQuery(Foo.class);
+ Root rootItem = criteriaItem.from(Foo.class);
+ listOrders.add(builder.asc(rootItem.get("name")));
+ listOrders.add(builder.asc(rootItem.get("id")));
+ criteriaItem.orderBy(listOrders.toArray(new Order[] {}));
+ final List fooList = session.createQuery(criteriaItem).getResultList();
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ /*@Test
+ public final void whenCriteriaSortingStringNullsLastAsc_thenNullsLast() {
+ final Criteria criteria = session.createCriteria(Foo.class, "FOO");
+ criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));
+ final List fooList = criteria.list();
+ assertNull(fooList.get(fooList.toArray().length - 1).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }
+
+ @Test
+ public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() {
+ final Criteria criteria = session.createCriteria(Foo.class, "FOO");
+ criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));
+ final List fooList = criteria.list();
+ assertNull(fooList.get(0).getName());
+ for (final Foo foo : fooList) {
+ System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName());
+ }
+ }*/
+
+ @Test
+ public final void whenSortingBars_thenBarsWithSortedFoos() {
+ final String hql = "FROM Bar b ORDER BY b.id";
+ final List barList = session.createQuery(hql).getResultList();
+ for (final Bar bar : barList) {
+ final Set fooSet = bar.getFooSet();
+ System.out.println("Bar Id:" + bar.getId());
+ for (final Foo foo : fooSet) {
+ System.out.println("FooName:" + foo.getName());
+ }
+ }
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
new file mode 100644
index 0000000000..b6cde868d3
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
@@ -0,0 +1,285 @@
+package com.baeldung.persistence.save;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import javax.persistence.PersistenceException;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.TransactionException;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.service.ServiceRegistry;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.baeldung.persistence.model.Person;
+
+/**
+ * Testing specific implementation details for different methods: persist, save,
+ * merge, update, saveOrUpdate.
+ */
+public class SaveMethodsTest {
+
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ Configuration configuration = new Configuration().addAnnotatedClass(Person.class)
+ .setProperty("hibernate.dialect", HSQLDialect.class.getName())
+ .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName())
+ .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
+ .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "")
+ .setProperty("hibernate.hbm2ddl.auto", "update");
+ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
+ configuration.getProperties()).build();
+ sessionFactory = configuration.buildSessionFactory(serviceRegistry);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void whenPersistTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenPersistPersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ session.persist(person);
+ Long id1 = person.getId();
+
+ session.persist(person);
+ Long id2 = person.getId();
+
+ assertEquals(id1, id2);
+ }
+
+ @Test(expected = PersistenceException.class)
+ public void whenPersistDetached_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+ session.evict(person);
+
+ session.persist(person);
+
+ }
+
+ @Test
+ public void whenSaveTransient_thenIdGeneratedImmediately() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ assertNull(person.getId());
+
+ Long id = (Long) session.save(person);
+
+ assertNotNull(id);
+
+ session.getTransaction().commit();
+ session.close();
+
+ assertEquals(id, person.getId());
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenSavePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ Long id2 = (Long) session.save(person);
+ assertEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenSaveDetached_thenNewInstancePersisted() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ session.evict(person);
+
+ Long id2 = (Long) session.save(person);
+ assertNotEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenMergeDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.flush();
+ session.evict(person);
+
+ person.setName("Mary");
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertNotSame(person, mergedPerson);
+ assertEquals("Mary", mergedPerson.getName());
+
+ }
+
+ @Test
+ public void whenMergeTransient_thenNewEntitySavedToDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ Person mergedPerson = (Person) session.merge(person);
+
+ session.getTransaction().commit();
+ session.beginTransaction();
+
+ assertNull(person.getId());
+ assertNotNull(mergedPerson.getId());
+
+ }
+
+ @Test
+ public void whenMergePersistent_thenReturnsSameObject() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertSame(person, mergedPerson);
+
+ }
+
+ @Test
+ public void whenUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.update(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test(expected = HibernateException.class)
+ public void whenUpdateTransient_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.saveOrUpdate(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.saveOrUpdate(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenSaveOrUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.saveOrUpdate(person);
+
+ }
+
+ @After
+ public void tearDown() {
+ try{
+ session.getTransaction().commit();
+ session.close();
+ }catch(TransactionException ex){
+ ex.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java
new file mode 100644
index 0000000000..c77f5dfb95
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+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.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooServiceBasicPersistenceIntegrationTest {
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private IFooService fooService;
+
+ private Session session;
+
+ // tests
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ fooService.create(new Foo(randomAlphabetic(6)));
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..b82d4621ab
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.dao.DataAccessException;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooServicePersistenceIntegrationTest {
+
+ @Autowired
+ @Qualifier("fooHibernateService")
+ private IFooService service;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenEntityIsCreated_thenNoExceptions() {
+ service.create(new Foo(randomAlphabetic(6)));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ @Ignore("work in progress")
+ public final void whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo());
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenEntityWithLongNameIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+ @Test(expected = InvalidDataAccessApiUsageException.class)
+ @Ignore("Right now, persist has saveOrUpdate semantics, so this will no longer fail")
+ public final void whenSameEntityIsCreatedTwice_thenDataException() {
+ final Foo entity = new Foo(randomAlphabetic(8));
+ service.create(entity);
+ service.create(entity);
+ }
+
+ @Test(expected = DataAccessException.class)
+ public final void temp_whenInvalidEntityIsCreated_thenDataException() {
+ service.create(new Foo(randomAlphabetic(2048)));
+ }
+
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
new file mode 100644
index 0000000000..cfd3844079
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
@@ -0,0 +1,114 @@
+package com.baeldung.persistence.service;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.exception.SQLGrammarException;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class FooStoredProceduresIntegrationTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresIntegrationTest.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private IFooService fooService;
+
+ private Session session;
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ Assume.assumeTrue(getAllFoosExists());
+ Assume.assumeTrue(getFoosByNameExists());
+ }
+
+ private boolean getFoosByNameExists() {
+ try {
+ session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ private boolean getAllFoosExists() {
+ try {
+ session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ @Test
+ public final void getAllFoosUsingStoredProcedures() {
+
+ fooService.create(new Foo(randomAlphabetic(6)));
+
+ // Stored procedure getAllFoos using createSQLQuery
+ List allFoos = session.createQuery("CALL GetAllFoos()", Foo.class).getResultList();
+ for (Foo foo : allFoos) {
+ LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName());
+ }
+ assertEquals(allFoos.size(), fooService.findAll().size());
+
+ // Stored procedure getAllFoos using a Named Query
+ @SuppressWarnings("unchecked")
+ List allFoos2 = session.getNamedQuery("callGetAllFoos").getResultList();
+ for (Foo foo : allFoos2) {
+ LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName());
+ }
+ assertEquals(allFoos2.size(), fooService.findAll().size());
+ }
+
+ @Test
+ public final void getFoosByNameUsingStoredProcedures() {
+
+ fooService.create(new Foo("NewFooName"));
+
+ // Stored procedure getFoosByName using createSQLQuery()
+ List allFoosByName = session.createQuery("CALL GetFoosByName(:fooName)", Foo.class)
+ .setParameter("fooName", "NewFooName").getResultList();
+ for (Foo foo : allFoosByName) {
+ LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString());
+ }
+
+ // Stored procedure getFoosByName using getNamedQuery()
+ @SuppressWarnings("unchecked")
+ List allFoosByName2 = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName")
+ .getResultList();
+ for (Foo foo : allFoosByName2) {
+ LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString());
+ }
+
+ }
+}
diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java
new file mode 100644
index 0000000000..9e8c4aba92
--- /dev/null
+++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java
@@ -0,0 +1,69 @@
+package com.baeldung.persistence.service;
+
+import com.baeldung.persistence.model.Child;
+import com.baeldung.persistence.model.Parent;
+import com.baeldung.spring.PersistenceConfig;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class ParentServicePersistenceIntegrationTest {
+
+ @Autowired
+ private IParentService service;
+
+ @Autowired
+ private IChildService childService;
+
+ // tests
+
+ @Test
+ public final void whenContextIsBootstrapped_thenNoExceptions() {
+ //
+ }
+
+ @Test
+ public final void whenOneToOneEntitiesAreCreated_thenNoExceptions() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ System.out.println("Child = " + childService.findOne(childEntity.getId()));
+ System.out.println("Child - parent = " + childService.findOne(childEntity.getId()).getParent());
+
+ System.out.println("Parent = " + service.findOne(parentEntity.getId()));
+ System.out.println("Parent - child = " + service.findOne(parentEntity.getId()).getChild());
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public final void whenChildIsDeletedWhileParentStillHasForeignKeyToIt_thenDataException() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ childService.delete(childEntity);
+ }
+
+ @Test
+ public final void whenChildIsDeletedAfterTheParent_thenNoExceptions() {
+ final Child childEntity = new Child();
+ childService.create(childEntity);
+
+ final Parent parentEntity = new Parent(childEntity);
+ service.create(parentEntity);
+
+ service.delete(parentEntity);
+ childService.delete(childEntity);
+ }
+
+}
diff --git a/spring-hibernate5/src/test/resources/.gitignore b/spring-hibernate5/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml
new file mode 100644
index 0000000000..9e0109aae2
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/com/baeldung/hibernate/criteria/model/Item.hbm.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/criteria.cfg.xml b/spring-hibernate5/src/test/resources/criteria.cfg.xml
new file mode 100644
index 0000000000..5bc3a32077
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/criteria.cfg.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/fetching.cfg.xml b/spring-hibernate5/src/test/resources/fetching.cfg.xml
new file mode 100644
index 0000000000..c47b062a2f
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/fetching.cfg.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml
new file mode 100644
index 0000000000..2e252e9307
--- /dev/null
+++ b/spring-hibernate5/src/test/resources/fetchingLazy.cfg.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ com.mysql.jdbc.Driver
+ jdbc:mysql://localhost:3306/test
+ root
+ root
+ org.hibernate.dialect.MySQLDialect
+ true
+
+
+
+
+
\ No newline at end of file