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