Author: adamw
Date: 2009-06-30 11:56:49 -0400 (Tue, 30 Jun 2009)
New Revision: 16981
Added:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/query/StoreDeletedData.java
Modified:
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java
Log:
HHH-3819:
- adding an option to store the data when an entity is deleted in the revision (instead of
having to read the last-but-one revision)
Modified:
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml
===================================================================
---
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2009-06-30
15:11:37 UTC (rev 16980)
+++
core/trunk/documentation/envers/src/main/docbook/en-US/content/configuration.xml 2009-06-30
15:56:49 UTC (rev 16981)
@@ -133,6 +133,21 @@
(their history won't be stored; it normally doesn't make
sense to store it).
</entry>
</row>
+ <row>
+ <entry>
+
<property>org.hibernate.envers.storeDataAtDelete</property>
+ </entry>
+ <entry>
+ false
+ </entry>
+ <entry>
+ Should the entity data be stored in the revision when the entity
is deleted (instead of only
+ storing the id and all other properties as null). This is not
normally needed, as the data is
+ present in the last-but-one revision. Sometimes, however, it is
easier and more efficient to
+ access it in the last revision (then the data that the entity
contained before deletion is
+ stored twice).
+ </entry>
+ </row>
</tbody>
</tgroup>
</table>
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java 2009-06-30
15:11:37 UTC (rev 16980)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/GlobalConfiguration.java 2009-06-30
15:56:49 UTC (rev 16981)
@@ -36,6 +36,9 @@
// Should the optimistic locking property of an entity be considered unversioned
private final boolean doNotAuditOptimisticLockingField;
+ // Should entity data be stored when it is deleted
+ private final boolean storeDataAtDelete;
+
/*
Which operator to use in correlated subqueries (when we want a property to be equal
to the result of
a correlated subquery, for example: e.p <operator> (select max(e2.p) where
e2.p2 = e.p2 ...).
@@ -53,6 +56,9 @@
"true");
doNotAuditOptimisticLockingField =
Boolean.parseBoolean(ignoreOptimisticLockingPropertyStr);
+ String storeDataDeletedEntityStr =
properties.getProperty("org.hibernate.envers.storeDataAtDelete",
"false");
+ storeDataAtDelete = Boolean.parseBoolean(storeDataDeletedEntityStr);
+
correlatedSubqueryOperator =
"org.hibernate.dialect.HSQLDialect".equals(
properties.getProperty("hibernate.dialect")) ? "in" :
"=";
}
@@ -68,4 +74,8 @@
public String getCorrelatedSubqueryOperator() {
return correlatedSubqueryOperator;
}
+
+ public boolean isStoreDataAtDelete() {
+ return storeDataAtDelete;
+ }
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java 2009-06-30
15:11:37 UTC (rev 16980)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java 2009-06-30
15:56:49 UTC (rev 16981)
@@ -174,7 +174,7 @@
AuditSync verSync = verCfg.getSyncManager().get(event.getSession());
verSync.addWorkUnit(new DelWorkUnit(event.getSession(),
event.getPersister().getEntityName(), verCfg,
- event.getId()));
+ event.getId(), event.getPersister(), event.getDeletedState()));
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(),
entityName, null,
event.getDeletedState(), event.getSession());
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java 2009-06-30
15:11:37 UTC (rev 16980)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/DelWorkUnit.java 2009-06-30
15:56:49 UTC (rev 16981)
@@ -31,14 +31,22 @@
import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.Session;
+import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.engine.SessionImplementor;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit {
- public DelWorkUnit(SessionImplementor sessionImplementor, String entityName,
AuditConfiguration verCfg, Serializable id) {
+ private final Object[] state;
+ private final String[] propertyNames;
+
+ public DelWorkUnit(SessionImplementor sessionImplementor, String entityName,
AuditConfiguration verCfg,
+ Serializable id, EntityPersister entityPersister, Object[] state) {
super(sessionImplementor, entityName, verCfg, id);
+
+ this.state = state;
+ this.propertyNames = entityPersister.getPropertyNames();
}
public boolean containsWork() {
@@ -49,6 +57,11 @@
Map<String, Object> data = new HashMap<String, Object>();
fillDataWithId(data, revisionData, RevisionType.DEL);
+ if (verCfg.getGlobalCfg().isStoreDataAtDelete()) {
+ verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor,
data,
+ propertyNames, state, state);
+ }
+
session.save(verCfg.getAuditEntCfg().getAuditEntityName(getEntityName()), data);
setPerformed(data);
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/query/StoreDeletedData.java
(from rev 16611,
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/query/SimpleQuery.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/query/StoreDeletedData.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/query/StoreDeletedData.java 2009-06-30
15:56:49 UTC (rev 16981)
@@ -0,0 +1,82 @@
+/*
+ * 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.query;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.envers.query.AuditEntity;
+import org.hibernate.envers.test.AbstractEntityTest;
+import org.hibernate.envers.test.entities.StrIntTestEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * A test which checks if the data of a deleted entity is stored when the setting is on.
+ * @author Adam Warski (adam at warski dot org)
+ */
+@SuppressWarnings({"unchecked"})
+public class StoreDeletedData extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(StrIntTestEntity.class);
+ cfg.setProperty("org.hibernate.envers.storeDataAtDelete", "true");
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ StrIntTestEntity site1 = new StrIntTestEntity("a", 10);
+
+ em.persist(site1);
+
+ id1 = site1.getId();
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ em.remove(site1);
+
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testRevisionsPropertyEqQuery() {
+ List revs_id1 = getAuditReader().createQuery()
+ .forRevisionsOfEntity(StrIntTestEntity.class, false, true)
+ .add(AuditEntity.id().eq(id1))
+ .getResultList();
+
+ assert revs_id1.size() == 2;
+ assert ((Object[]) revs_id1.get(0))[0].equals(new StrIntTestEntity("a",
10, id1));
+ assert ((Object[]) revs_id1.get(1))[0].equals(new StrIntTestEntity("a",
10, id1));
+ }
+}
\ No newline at end of file