diff --git a/spring-hibernate4/pom.xml b/spring-hibernate4/pom.xml
index 8fabb56ab7..f3c2806353 100644
--- a/spring-hibernate4/pom.xml
+++ b/spring-hibernate4/pom.xml
@@ -15,6 +15,16 @@
spring-context
${org.springframework.version}
+
+ org.springframework
+ spring-aspects
+ ${org.springframework.version}
+
+
+ org.springframework.security
+ spring-security-core
+ ${org.springframework.security.version}
+
@@ -23,21 +33,35 @@
spring-orm
${org.springframework.version}
+
+ org.springframework.data
+ spring-data-jpa
+ ${org.springframework.data.version}
+
org.hibernate
hibernate-core
${hibernate.version}
- org.javassist
- javassist
- ${javassist.version}
+ org.hibernate
+ hibernate-envers
+ ${hibernate-envers.version}
+
+
+ javax.transaction
+ jta
+ ${jta.version}
+
+
+ javax.el
+ javax.el-api
+ ${el-api.version}
mysql
mysql-connector-java
${mysql-connector-java.version}
- runtime
@@ -82,7 +106,7 @@
${org.springframework.version}
test
-
+
junit
junit
@@ -90,12 +114,27 @@
test
+
+ org.springframework.security
+ spring-security-test
+ ${org.springframework.security.version}
+ test
+
+
org.hamcrest
hamcrest-core
${org.hamcrest.version}
test
+
+
+ junit
+ junit-dep
+ ${junit.version}
+ test
+
+
org.hamcrest
hamcrest-library
@@ -175,18 +214,22 @@
4.2.4.RELEASE
- 4.0.3.RELEASE
- 3.20.0-GA
-
+ 4.0.3.RELEASE
+ 1.9.2.RELEASE
+ 3.20.0-GA
+
4.3.11.Final
+ ${hibernate.version}
5.1.37
7.0.42
+ 1.1
+ 2.2.4
1.7.13
1.1.3
-
+
5.2.2.Final
@@ -196,7 +239,7 @@
1.3
- 4.12
+ 4.11
1.10.19
4.4.1
@@ -209,7 +252,8 @@
2.18.1
2.7
1.4.15
+
-
\ No newline at end of file
+
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarAuditableDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarAuditableDao.java
new file mode 100644
index 0000000000..060922942b
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarAuditableDao.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.dao;
+
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableDao extends IBarDao, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarCrudRepository.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarCrudRepository.java
new file mode 100644
index 0000000000..70fffd9d80
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarCrudRepository.java
@@ -0,0 +1,10 @@
+package org.baeldung.persistence.dao;
+
+import java.io.Serializable;
+
+import org.baeldung.persistence.model.Bar;
+import org.springframework.data.repository.CrudRepository;
+
+public interface IBarCrudRepository extends CrudRepository {
+ //
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarDao.java
new file mode 100644
index 0000000000..02814b39b8
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IBarDao.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.dao;
+
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Bar;
+
+public interface IBarDao extends IOperations {
+ //
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooAuditableDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooAuditableDao.java
new file mode 100644
index 0000000000..ee0cc1fb8a
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooAuditableDao.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.dao;
+
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableDao extends IFooDao, IAuditOperations {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractDao.java
new file mode 100644
index 0000000000..6a1790ad3e
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractDao.java
@@ -0,0 +1,14 @@
+package org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
new file mode 100644
index 0000000000..f0886c612e
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java
@@ -0,0 +1,37 @@
+package org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java
index 65e57afcb3..dd22d94503 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java
@@ -10,55 +10,49 @@ import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Preconditions;
@SuppressWarnings("unchecked")
-public abstract class AbstractHibernateDao implements IOperations {
- private Class clazz;
+public abstract class AbstractHibernateDao extends AbstractDao implements IOperations {
@Autowired
- private SessionFactory sessionFactory;
+ protected SessionFactory sessionFactory;
// API
- protected final void setClazz(final Class clazzToSet) {
- clazz = Preconditions.checkNotNull(clazzToSet);
- }
-
@Override
- public final T findOne(final long id) {
+ public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
@Override
- public final List findAll() {
+ public List findAll() {
return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
@Override
- public final void create(final T entity) {
+ public void create(final T entity) {
Preconditions.checkNotNull(entity);
- // getCurrentSession().persist(entity);
getCurrentSession().saveOrUpdate(entity);
}
@Override
- public final T update(final T entity) {
+ public T update(final T entity) {
Preconditions.checkNotNull(entity);
return (T) getCurrentSession().merge(entity);
}
@Override
- public final void delete(final T entity) {
+ public void delete(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().delete(entity);
}
@Override
- public final void deleteById(final long entityId) {
+ public void deleteById(final long entityId) {
final T entity = findOne(entityId);
Preconditions.checkState(entity != null);
delete(entity);
}
- protected final Session getCurrentSession() {
+ protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractJpaDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractJpaDao.java
new file mode 100644
index 0000000000..7e08151bea
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractJpaDao.java
@@ -0,0 +1,56 @@
+package org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IAuditOperations.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IAuditOperations.java
new file mode 100644
index 0000000000..bcc1059dbe
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IAuditOperations.java
@@ -0,0 +1,14 @@
+package org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarAuditableDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarAuditableDao.java
new file mode 100644
index 0000000000..bddd98bcfb
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarAuditableDao.java
@@ -0,0 +1,28 @@
+package org.baeldung.persistence.dao.impl;
+
+import java.util.List;
+
+import org.baeldung.persistence.dao.IBarAuditableDao;
+import org.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarDao.java
new file mode 100644
index 0000000000..ba48581edb
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarDao.java
@@ -0,0 +1,19 @@
+package org.baeldung.persistence.dao.impl;
+
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.common.AbstractHibernateDao;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarJpaDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarJpaDao.java
new file mode 100644
index 0000000000..cd167dd64f
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/BarJpaDao.java
@@ -0,0 +1,19 @@
+package org.baeldung.persistence.dao.impl;
+
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.common.AbstractJpaDao;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooAuditableDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooAuditableDao.java
new file mode 100644
index 0000000000..ee9cc639b5
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooAuditableDao.java
@@ -0,0 +1,17 @@
+package org.baeldung.persistence.dao.impl;
+
+import org.baeldung.persistence.dao.IFooAuditableDao;
+import org.baeldung.persistence.dao.common.AbstractHibernateAuditableDao;
+import org.baeldung.persistence.model.Foo;
+
+public class FooAuditableDao extends AbstractHibernateAuditableDao implements IFooAuditableDao {
+
+ public FooAuditableDao() {
+ super();
+
+ setClazz(Foo.class);
+ }
+
+ // API
+
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
index eb3a66126c..b8360160da 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
@@ -6,7 +6,7 @@ import org.baeldung.persistence.model.Foo;
import org.springframework.stereotype.Repository;
@Repository
-public class FooDao extends AbstractHibernateDaoimplements IFooDao {
+public class FooDao extends AbstractHibernateDao implements IFooDao {
public FooDao() {
super();
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java
index 410ad79b02..1d4ec69741 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java
@@ -1,26 +1,66 @@
package org.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")
@@ -31,8 +71,31 @@ public class Bar implements Serializable {
@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")
+ @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();
}
@@ -69,7 +132,57 @@ public class Bar implements Serializable {
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() {
@@ -103,4 +216,27 @@ public class Bar implements Serializable {
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-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java
index 974535e058..9a96594cfe 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java
@@ -12,7 +12,11 @@ import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
+import org.hibernate.envers.Audited;
+
@Entity
+@Audited
+// @Proxy(lazy = false)
public class Foo implements Serializable {
@Id
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarAuditableService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarAuditableService.java
new file mode 100644
index 0000000000..b481dfefeb
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarAuditableService.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.service;
+
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.model.Bar;
+
+public interface IBarAuditableService extends IBarService, IAuditOperations {
+
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarService.java
new file mode 100644
index 0000000000..145a0d54db
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IBarService.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.service;
+
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Bar;
+
+public interface IBarService extends IOperations {
+ //
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooAuditableService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooAuditableService.java
new file mode 100644
index 0000000000..2bd9ccb208
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooAuditableService.java
@@ -0,0 +1,8 @@
+package org.baeldung.persistence.service;
+
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.model.Foo;
+
+public interface IFooAuditableService extends IFooService, IAuditOperations {
+ //
+}
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
new file mode 100644
index 0000000000..f9b6703607
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateAuditableService.java
@@ -0,0 +1,30 @@
+package org.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateService.java
new file mode 100644
index 0000000000..3539a56896
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractHibernateService.java
@@ -0,0 +1,42 @@
+package org.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractJpaService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractJpaService.java
new file mode 100644
index 0000000000..2b41edda12
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractJpaService.java
@@ -0,0 +1,42 @@
+package org.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
index 3b32bc3ebb..530bc5e956 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java
@@ -4,9 +4,7 @@ import java.io.Serializable;
import java.util.List;
import org.baeldung.persistence.dao.common.IOperations;
-import org.springframework.transaction.annotation.Transactional;
-@Transactional
public abstract class AbstractService implements IOperations {
@Override
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
new file mode 100644
index 0000000000..dfb73204c2
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractSpringDataJpaService.java
@@ -0,0 +1,46 @@
+package org.baeldung.persistence.service.common;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarAuditableService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarAuditableService.java
new file mode 100644
index 0000000000..9124a41a56
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarAuditableService.java
@@ -0,0 +1,41 @@
+package org.baeldung.persistence.service.impl;
+
+import org.baeldung.persistence.dao.IBarAuditableDao;
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.service.IBarAuditableService;
+import org.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarJpaService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarJpaService.java
new file mode 100644
index 0000000000..d78fbdd7c4
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarJpaService.java
@@ -0,0 +1,30 @@
+package org.baeldung.persistence.service.impl;
+
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.service.IBarService;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarService.java
new file mode 100644
index 0000000000..7fdd1b026d
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarService.java
@@ -0,0 +1,30 @@
+package org.baeldung.persistence.service.impl;
+
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.service.IBarService;
+import org.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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarSpringDataJpaService.java
new file mode 100644
index 0000000000..65f665495a
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/BarSpringDataJpaService.java
@@ -0,0 +1,26 @@
+package org.baeldung.persistence.service.impl;
+
+import java.io.Serializable;
+
+import org.baeldung.persistence.dao.IBarCrudRepository;
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.service.IBarService;
+import org.baeldung.persistence.service.common.AbstractSpringDataJpaService;
+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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
index 71b1bc697e..17f5c36e48 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
@@ -4,12 +4,12 @@ import org.baeldung.persistence.dao.IChildDao;
import org.baeldung.persistence.dao.common.IOperations;
import org.baeldung.persistence.model.Child;
import org.baeldung.persistence.service.IChildService;
-import org.baeldung.persistence.service.common.AbstractService;
+import org.baeldung.persistence.service.common.AbstractHibernateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
-public class ChildService extends AbstractServiceimplements IChildService {
+public class ChildService extends AbstractHibernateServiceimplements IChildService {
@Autowired
private IChildDao dao;
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooAuditableService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooAuditableService.java
new file mode 100644
index 0000000000..bef9ba5fad
--- /dev/null
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooAuditableService.java
@@ -0,0 +1,41 @@
+package org.baeldung.persistence.service.impl;
+
+import org.baeldung.persistence.dao.IFooAuditableDao;
+import org.baeldung.persistence.dao.IFooDao;
+import org.baeldung.persistence.dao.common.IAuditOperations;
+import org.baeldung.persistence.dao.common.IOperations;
+import org.baeldung.persistence.model.Foo;
+import org.baeldung.persistence.service.IFooAuditableService;
+import org.baeldung.persistence.service.common.AbstractHibernateAuditableService;
+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-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java
index 8a89153dd0..65b5cdec5c 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java
@@ -4,14 +4,16 @@ import org.baeldung.persistence.dao.IFooDao;
import org.baeldung.persistence.dao.common.IOperations;
import org.baeldung.persistence.model.Foo;
import org.baeldung.persistence.service.IFooService;
-import org.baeldung.persistence.service.common.AbstractService;
+import org.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 AbstractServiceimplements IFooService {
+public class FooService extends AbstractHibernateServiceimplements IFooService {
@Autowired
+ @Qualifier("fooHibernateDao")
private IFooDao dao;
public FooService() {
diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
index 1f9b602350..b78ae53264 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
@@ -4,12 +4,12 @@ import org.baeldung.persistence.dao.IParentDao;
import org.baeldung.persistence.dao.common.IOperations;
import org.baeldung.persistence.model.Parent;
import org.baeldung.persistence.service.IParentService;
-import org.baeldung.persistence.service.common.AbstractService;
+import org.baeldung.persistence.service.common.AbstractHibernateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
-public class ParentService extends AbstractServiceimplements IParentService {
+public class ParentService extends AbstractHibernateServiceimplements IParentService {
@Autowired
private IParentDao dao;
diff --git a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java b/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java
index 000c67d625..ae7ecf3439 100644
--- a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java
+++ b/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java
@@ -5,7 +5,24 @@ import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
-import org.hibernate.SessionFactory;
+import org.baeldung.persistence.dao.IBarAuditableDao;
+import org.baeldung.persistence.dao.IBarDao;
+import org.baeldung.persistence.dao.IFooAuditableDao;
+import org.baeldung.persistence.dao.IFooDao;
+import org.baeldung.persistence.dao.impl.BarAuditableDao;
+import org.baeldung.persistence.dao.impl.BarDao;
+import org.baeldung.persistence.dao.impl.BarJpaDao;
+import org.baeldung.persistence.dao.impl.FooAuditableDao;
+import org.baeldung.persistence.dao.impl.FooDao;
+import org.baeldung.persistence.service.IBarAuditableService;
+import org.baeldung.persistence.service.IBarService;
+import org.baeldung.persistence.service.IFooAuditableService;
+import org.baeldung.persistence.service.IFooService;
+import org.baeldung.persistence.service.impl.BarAuditableService;
+import org.baeldung.persistence.service.impl.BarJpaService;
+import org.baeldung.persistence.service.impl.BarSpringDataJpaService;
+import org.baeldung.persistence.service.impl.FooAuditableService;
+import org.baeldung.persistence.service.impl.FooService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@@ -13,14 +30,23 @@ 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.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.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.google.common.base.Preconditions;
@Configuration
@EnableTransactionManagement
+@EnableJpaRepositories(basePackages = { "org.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager")
+@EnableJpaAuditing
@PropertySource({ "classpath:persistence-mysql.properties" })
@ComponentScan({ "org.baeldung.persistence" })
public class PersistenceConfig {
@@ -42,6 +68,19 @@ public class PersistenceConfig {
return sessionFactory;
}
+ @Bean
+ public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
+ final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
+ emf.setDataSource(restDataSource());
+ emf.setPackagesToScan(new String[] { "org.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();
@@ -54,12 +93,17 @@ public class PersistenceConfig {
}
@Bean
- @Autowired
- public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) {
- final HibernateTransactionManager txManager = new HibernateTransactionManager();
- txManager.setSessionFactory(sessionFactory);
+ public PlatformTransactionManager hibernateTransactionManager() {
+ final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
+ transactionManager.setSessionFactory(sessionFactory().getObject());
+ return transactionManager;
+ }
- return txManager;
+ @Bean
+ public PlatformTransactionManager jpaTransactionManager() {
+ final JpaTransactionManager transactionManager = new JpaTransactionManager();
+ transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
+ return transactionManager;
}
@Bean
@@ -67,7 +111,57 @@ public class PersistenceConfig {
return new PersistenceExceptionTranslationPostProcessor();
}
- final Properties hibernateProperties() {
+ @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"));
@@ -76,6 +170,9 @@ public class PersistenceConfig {
// hibernateProperties.setProperty("hibernate.format_sql", "true");
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
+ // Envers properties
+ hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix"));
+
return hibernateProperties;
}
diff --git a/spring-hibernate4/src/main/resources/persistence-mysql.properties b/spring-hibernate4/src/main/resources/persistence-mysql.properties
index 8263b0d9ac..f6b6ab6fca 100644
--- a/spring-hibernate4/src/main/resources/persistence-mysql.properties
+++ b/spring-hibernate4/src/main/resources/persistence-mysql.properties
@@ -8,3 +8,6 @@ jdbc.pass=tutorialmy5ql
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-hibernate4/src/main/resources/webSecurityConfig.xml b/spring-hibernate4/src/main/resources/webSecurityConfig.xml
index 88af78dabc..d9423d31e7 100644
--- a/spring-hibernate4/src/main/resources/webSecurityConfig.xml
+++ b/spring-hibernate4/src/main/resources/webSecurityConfig.xml
@@ -5,7 +5,8 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"
>
-
+
+
diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/AuditTestSuite.java b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/AuditTestSuite.java
new file mode 100644
index 0000000000..d3a0ab9cb6
--- /dev/null
+++ b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/AuditTestSuite.java
@@ -0,0 +1,14 @@
+package org.baeldung.persistence.audit;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({ // @formatter:off
+ EnversFooBarAuditTest.class,
+ JPABarAuditTest.class,
+ SpringDataJPABarAuditTest.class
+}) // @formatter:on
+public class AuditTestSuite {
+ //
+}
\ No newline at end of file
diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/EnversFooBarAuditTest.java b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/EnversFooBarAuditTest.java
new file mode 100644
index 0000000000..7720253237
--- /dev/null
+++ b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/EnversFooBarAuditTest.java
@@ -0,0 +1,142 @@
+package org.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.model.Foo;
+import org.baeldung.persistence.service.IBarAuditableService;
+import org.baeldung.persistence.service.IFooAuditableService;
+import org.baeldung.spring.PersistenceConfig;
+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 EnversFooBarAuditTest {
+
+ private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditTest.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-hibernate4/src/test/java/org/baeldung/persistence/audit/JPABarAuditTest.java b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/JPABarAuditTest.java
new file mode 100644
index 0000000000..3f1353ba8c
--- /dev/null
+++ b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/JPABarAuditTest.java
@@ -0,0 +1,106 @@
+package org.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 org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.model.Bar.OPERATION;
+import org.baeldung.persistence.service.IBarService;
+import org.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 JPABarAuditTest {
+
+ private static Logger logger = LoggerFactory.getLogger(JPABarAuditTest.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-hibernate4/src/test/java/org/baeldung/persistence/audit/SpringDataJPABarAuditTest.java b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/SpringDataJPABarAuditTest.java
new file mode 100644
index 0000000000..bddaac4011
--- /dev/null
+++ b/spring-hibernate4/src/test/java/org/baeldung/persistence/audit/SpringDataJPABarAuditTest.java
@@ -0,0 +1,76 @@
+package org.baeldung.persistence.audit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.baeldung.persistence.model.Bar;
+import org.baeldung.persistence.service.IBarService;
+import org.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 SpringDataJPABarAuditTest {
+
+ private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditTest.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-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
index 07c6ba3382..37781aeb22 100644
--- a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
+++ b/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java
@@ -8,6 +8,7 @@ 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;
@@ -20,6 +21,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader;
public class FooServicePersistenceIntegrationTest {
@Autowired
+ @Qualifier("fooHibernateService")
private IFooService service;
// tests