Author: adamw
Date: 2009-04-30 03:36:14 -0400 (Thu, 30 Apr 2009)
New Revision: 16485
Added:
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/reventity/CustomDataRevEntity.java
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomNoListener.java
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/AuditReader.java
core/trunk/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/AuditSync.java
Log:
HHH-3823:
- adding a method to obtain the current revision entity + test
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/AuditReader.java
===================================================================
--- core/trunk/envers/src/main/java/org/hibernate/envers/AuditReader.java 2009-04-30
05:53:15 UTC (rev 16484)
+++ core/trunk/envers/src/main/java/org/hibernate/envers/AuditReader.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -100,6 +100,20 @@
<T> T findRevision(Class<T> revisionEntityClass, Number revision) throws
IllegalArgumentException,
RevisionDoesNotExistException, IllegalStateException;
+ /**
+ * Gets an instance of the current revision entity, to which any entries in the audit
tables will be bound.
+ * Please note the if {@code persist} is {@code false}, and no audited entities are
modified in this session,
+ * then the obtained revision entity instance won't be persisted. If {@code persist}
is {@code true}, the revision
+ * entity instance will always be persisted, regardless of whether audited entities are
changed or not.
+ * @param revisionEntityClass Class of the revision entity. Should be annotated with
{@link RevisionEntity}.
+ * @param persist If the revision entity is not yet persisted, should it become
persisted. This way, the primary
+ * identifier (id) will be filled (if it's assigned by the DB) and available, but
the revision entity will be
+ * persisted even if there are no changes to audited entities. Otherwise, the revision
number (id) can be
+ * {@code null}.
+ * @return The current revision entity, to which any entries in the audit tables will be
bound.
+ */
+ <T> T getCurrentRevision(Class<T> revisionEntityClass, boolean persist);
+
/**
*
* @return A query creator, associated with this AuditReader instance, with which
queries can be
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java 2009-04-30
05:53:15 UTC (rev 16484)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -34,10 +34,12 @@
import org.hibernate.envers.query.AuditEntity;
import static org.hibernate.envers.tools.ArgumentsTools.checkNotNull;
import static org.hibernate.envers.tools.ArgumentsTools.checkPositive;
+import org.hibernate.envers.synchronization.AuditSync;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.hibernate.Session;
+import org.hibernate.event.EventSource;
import org.hibernate.engine.SessionImplementor;
import org.jboss.envers.query.VersionsQueryCreator;
@@ -190,7 +192,20 @@
}
}
- public VersionsQueryCreator createQuery() {
+ @SuppressWarnings({"unchecked"})
+ public <T> T getCurrentRevision(Class<T> revisionEntityClass, boolean
persist) {
+ if (!(session instanceof EventSource)) {
+ throw new IllegalArgumentException("The provided session is not an
EventSource!");
+ }
+
+ // Obtaining the current audit sync
+ AuditSync auditSync = verCfg.getSyncManager().get((EventSource) session);
+
+ // And getting the current revision data
+ return (T) auditSync.getCurrentRevisionData(session, persist);
+ }
+
+ public VersionsQueryCreator createQuery() {
return new VersionsQueryCreator(verCfg, this);
}
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java 2009-04-30
05:53:15 UTC (rev 16484)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/DefaultRevisionInfoGenerator.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -63,14 +63,18 @@
}
}
- private Object newRevision() {
- Object revisionInfo;
+ public void saveRevisionData(Session session, Object revisionData) {
+ session.save(revisionInfoEntityName, revisionData);
+ }
+
+ public Object generate() {
+ Object revisionInfo;
try {
revisionInfo = revisionInfoClass.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
-
+
revisionTimestampSetter.set(revisionInfo, System.currentTimeMillis(), null);
if (listener != null) {
@@ -79,10 +83,4 @@
return revisionInfo;
}
-
- public Object generate(Session session) {
- Object revisionData = newRevision();
- session.save(revisionInfoEntityName, revisionData);
- return revisionData;
- }
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java 2009-04-30
05:53:15 UTC (rev 16484)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/revisioninfo/RevisionInfoGenerator.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -29,5 +29,6 @@
* @author Adam Warski (adam at warski dot org)
*/
public interface RevisionInfoGenerator {
- Object generate(Session session);
+ void saveRevisionData(Session session, Object revisionData);
+ Object generate();
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/AuditSync.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/AuditSync.java 2009-04-30
05:53:15 UTC (rev 16484)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/AuditSync.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -111,9 +111,8 @@
}
private void executeInSession(Session session) {
- if (revisionData == null) {
- revisionData = revisionInfoGenerator.generate(session);
- }
+ // Making sure the revision data is persisted.
+ getCurrentRevisionData(session, true);
AuditWorkUnit vwu;
@@ -127,6 +126,20 @@
}
}
+ public Object getCurrentRevisionData(Session session, boolean persist) {
+ // Generating the revision data if not yet generated
+ if (revisionData == null) {
+ revisionData = revisionInfoGenerator.generate();
+ }
+
+ // Saving the revision data, if not yet saved and persist is true
+ if (!session.contains(revisionData) && persist) {
+ revisionInfoGenerator.saveRevisionData(session, revisionData);
+ }
+
+ return revisionData;
+ }
+
public void beforeCompletion() {
if (workUnits.size() == 0 && undoQueue.size() == 0) {
return;
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/reventity/CustomDataRevEntity.java
(from rev 16482,
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/reventity/CustomRevEntity.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/reventity/CustomDataRevEntity.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/reventity/CustomDataRevEntity.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -0,0 +1,95 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.envers.test.entities.reventity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.hibernate.envers.RevisionEntity;
+import org.hibernate.envers.RevisionNumber;
+import org.hibernate.envers.RevisionTimestamp;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+@Entity
+@RevisionEntity
+public class CustomDataRevEntity {
+ @Id
+ @GeneratedValue
+ @RevisionNumber
+ private int customId;
+
+ @RevisionTimestamp
+ private long customTimestamp;
+
+ private String data;
+
+ public int getCustomId() {
+ return customId;
+ }
+
+ public void setCustomId(int customId) {
+ this.customId = customId;
+ }
+
+ public long getCustomTimestamp() {
+ return customTimestamp;
+ }
+
+ public void setCustomTimestamp(long customTimestamp) {
+ this.customTimestamp = customTimestamp;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof CustomDataRevEntity)) return false;
+
+ CustomDataRevEntity that = (CustomDataRevEntity) o;
+
+ if (customId != that.customId) return false;
+ if (customTimestamp != that.customTimestamp) return false;
+ if (data != null ? !data.equals(that.data) : that.data != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = customId;
+ result = 31 * result + (int) (customTimestamp ^ (customTimestamp >>> 32));
+ result = 31 * result + (data != null ? data.hashCode() : 0);
+ return result;
+ }
+}
\ No newline at end of file
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomNoListener.java
(from rev 16482,
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/reventity/Custom.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomNoListener.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/reventity/CustomNoListener.java 2009-04-30
07:36:14 UTC (rev 16485)
@@ -0,0 +1,137 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors. All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.envers.test.integration.reventity;
+
+import java.util.Arrays;
+import java.util.Date;
+import javax.persistence.EntityManager;
+
+import org.hibernate.envers.AuditReader;
+import org.hibernate.envers.exception.RevisionDoesNotExistException;
+import org.hibernate.envers.test.AbstractEntityTest;
+import org.hibernate.envers.test.entities.StrTestEntity;
+import org.hibernate.envers.test.entities.reventity.CustomDataRevEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.hibernate.ejb.Ejb3Configuration;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class CustomNoListener extends AbstractEntityTest {
+ private Integer id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrTestEntity.class);
+ cfg.addAnnotatedClass(CustomDataRevEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() throws InterruptedException {
+ EntityManager em = getEntityManager();
+
+ // Revision 1
+ em.getTransaction().begin();
+ StrTestEntity te = new StrTestEntity("x");
+ em.persist(te);
+ id = te.getId();
+
+ // Setting the data on the revision entity
+ CustomDataRevEntity custom =
getAuditReader().getCurrentRevision(CustomDataRevEntity.class, false);
+ custom.setData("data1");
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("y");
+
+ // Setting the data on the revision entity
+ custom = getAuditReader().getCurrentRevision(CustomDataRevEntity.class, false);
+ custom.setData("data2");
+
+ em.getTransaction().commit();
+
+ // Revision 3 - no changes, but rev entity should be persisted
+ em.getTransaction().begin();
+
+ // Setting the data on the revision entity
+ custom = getAuditReader().getCurrentRevision(CustomDataRevEntity.class, true);
+ custom.setData("data3");
+
+ em.getTransaction().commit();
+
+ // No changes, rev entity won't be persisted
+ em.getTransaction().begin();
+
+ // Setting the data on the revision entity
+ custom = getAuditReader().getCurrentRevision(CustomDataRevEntity.class, false);
+ custom.setData("data4");
+
+ em.getTransaction().commit();
+
+ // Revision 4
+ em.getTransaction().begin();
+ te = em.find(StrTestEntity.class, id);
+ te.setStr("z");
+
+ // Setting the data on the revision entity
+ custom = getAuditReader().getCurrentRevision(CustomDataRevEntity.class, false);
+ custom.setData("data5");
+
+ custom = getAuditReader().getCurrentRevision(CustomDataRevEntity.class, false);
+ custom.setData("data5bis");
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testFindRevision() {
+ AuditReader vr = getAuditReader();
+
+ assert "data1".equals(vr.findRevision(CustomDataRevEntity.class,
1).getData());
+ assert "data2".equals(vr.findRevision(CustomDataRevEntity.class,
2).getData());
+ assert "data3".equals(vr.findRevision(CustomDataRevEntity.class,
3).getData());
+ assert "data5bis".equals(vr.findRevision(CustomDataRevEntity.class,
4).getData());
+ }
+
+ @Test
+ public void testRevisionsCounts() {
+ assert Arrays.asList(1, 2,
4).equals(getAuditReader().getRevisions(StrTestEntity.class, id));
+ }
+
+ @Test
+ public void testHistoryOfId1() {
+ StrTestEntity ver1 = new StrTestEntity("x", id);
+ StrTestEntity ver2 = new StrTestEntity("y", id);
+ StrTestEntity ver3 = new StrTestEntity("z", id);
+
+ assert getAuditReader().find(StrTestEntity.class, id, 1).equals(ver1);
+ assert getAuditReader().find(StrTestEntity.class, id, 2).equals(ver2);
+ assert getAuditReader().find(StrTestEntity.class, id, 3).equals(ver2);
+ assert getAuditReader().find(StrTestEntity.class, id, 4).equals(ver3);
+ }
+}
\ No newline at end of file