Author: adamw
Date: 2008-10-01 06:26:59 -0400 (Wed, 01 Oct 2008)
New Revision: 173
Added:
trunk/src/main/org/jboss/envers/reader/FirstLevelCache.java
trunk/src/test/org/jboss/envers/test/integration/cache/
trunk/src/test/org/jboss/envers/test/integration/cache/OneToManyCache.java
trunk/src/test/org/jboss/envers/test/integration/cache/OneToOneCache.java
trunk/src/test/org/jboss/envers/test/integration/cache/QueryCache.java
Modified:
trunk/resources/test/testng.xml
trunk/src/main/org/jboss/envers/entities/EntityInstantiator.java
trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
trunk/src/main/org/jboss/envers/reader/VersionsReaderImpl.java
trunk/src/main/org/jboss/envers/reader/VersionsReaderImplementor.java
trunk/src/main/org/jboss/envers/tools/ConcurrentReferenceHashMap.java
trunk/src/main/org/jboss/envers/tools/Tools.java
Log:
ENVERS-54: first level cache (versions-reader scoped)
Modified: trunk/resources/test/testng.xml
===================================================================
--- trunk/resources/test/testng.xml 2008-09-26 15:33:14 UTC (rev 172)
+++ trunk/resources/test/testng.xml 2008-10-01 10:26:59 UTC (rev 173)
@@ -4,6 +4,7 @@
<test name="All">
<packages>
<package name="org.jboss.envers.test.integration.basic" />
+ <package name="org.jboss.envers.test.integration.cache" />
<package name="org.jboss.envers.test.integration.collection"
/>
<package
name="org.jboss.envers.test.integration.collection.mapkey" />
<package name="org.jboss.envers.test.integration.components"
/>
Modified: trunk/src/main/org/jboss/envers/entities/EntityInstantiator.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/EntityInstantiator.java 2008-09-26 15:33:14
UTC (rev 172)
+++ trunk/src/main/org/jboss/envers/entities/EntityInstantiator.java 2008-10-01 10:26:59
UTC (rev 173)
@@ -63,6 +63,18 @@
entityName = type;
}
+ // First mapping the primary key
+ IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
+ Map originalId = (Map)
versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
+
+ Object primaryKey = idMapper.mapToIdFromMap(originalId);
+
+ // Checking if the entity is in cache
+ if (versionsReader.getFirstLevelCache().contains(entityName, revision,
primaryKey)) {
+ return versionsReader.getFirstLevelCache().get(entityName, revision,
primaryKey);
+ }
+
+ // If it is not in the cache, creating a new entity instance
Object ret;
try {
Class<?> cls = ReflectionTools.loadClass(entityName);
@@ -71,11 +83,10 @@
throw new VersionsException(e);
}
- IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
- Map originalId = (Map)
versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
+ // Putting the newly created entity instance into the first level cache, in case
a one-to-one bidirectional
+ // relation is present (which is eagerly loaded).
+ versionsReader.getFirstLevelCache().put(entityName, revision, primaryKey, ret);
- Object primaryKey = idMapper.mapToIdFromMap(originalId);
-
verCfg.getEntCfg().get(entityName).getPropertyMapper().mapToEntityFromMap(verCfg,
ret, versionsEntity, primaryKey,
versionsReader, revision);
idMapper.mapToEntityFromMap(ret, originalId);
Modified: trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java
===================================================================
--- trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java 2008-09-26
15:33:14 UTC (rev 172)
+++ trunk/src/main/org/jboss/envers/entities/mapper/relation/ToOneIdMapper.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -71,10 +71,14 @@
if (entityId == null) {
value = null;
} else {
- Class<?> entityClass =
ReflectionTools.loadClass(referencedEntityName);
+ if (versionsReader.getFirstLevelCache().contains(referencedEntityName,
revision, entityId)) {
+ value = versionsReader.getFirstLevelCache().get(referencedEntityName,
revision, entityId);
+ } else {
+ Class<?> entityClass =
ReflectionTools.loadClass(referencedEntityName);
- value =
versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
- createProxy(null, new ToOneDelegateSessionImplementor(versionsReader,
entityClass, entityId, revision));
+ value =
versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName).
+ createProxy(null, new
ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision));
+ }
}
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
@@ -82,9 +86,9 @@
}
public List<PersistentCollectionChangeData> mapCollectionChanges(String
referencingPropertyName,
-
PersistentCollection newColl,
-
Serializable oldColl,
-
Serializable id) {
+ PersistentCollection
newColl,
+ Serializable
oldColl,
+ Serializable id) {
return null;
}
}
Added: trunk/src/main/org/jboss/envers/reader/FirstLevelCache.java
===================================================================
--- trunk/src/main/org/jboss/envers/reader/FirstLevelCache.java
(rev 0)
+++ trunk/src/main/org/jboss/envers/reader/FirstLevelCache.java 2008-10-01 10:26:59 UTC
(rev 173)
@@ -0,0 +1,32 @@
+package org.jboss.envers.reader;
+
+import org.jboss.envers.tools.Triple;
+import static org.jboss.envers.tools.Triple.*;
+import static org.jboss.envers.tools.Tools.newHashMap;
+
+import java.util.Map;
+
+/**
+ * First level cache for versioned entities, versions reader-scoped. Each entity is
uniquely identified by a
+ * revision number and entity id.
+ * @author Adam Warski (adam at warski dot org)
+ */
+public class FirstLevelCache {
+ private final Map<Triple<String, Number, Object>, Object> cache;
+
+ public FirstLevelCache() {
+ cache = newHashMap();
+ }
+
+ public Object get(String entityName, Number revision, Object id) {
+ return cache.get(make(entityName, revision, id));
+ }
+
+ public void put(String entityName, Number revision, Object id, Object entity) {
+ cache.put(make(entityName, revision, id), entity);
+ }
+
+ public boolean contains(String entityName, Number revision, Object id) {
+ return cache.containsKey(make(entityName, revision, id));
+ }
+}
Modified: trunk/src/main/org/jboss/envers/reader/VersionsReaderImpl.java
===================================================================
--- trunk/src/main/org/jboss/envers/reader/VersionsReaderImpl.java 2008-09-26 15:33:14 UTC
(rev 172)
+++ trunk/src/main/org/jboss/envers/reader/VersionsReaderImpl.java 2008-10-01 10:26:59 UTC
(rev 173)
@@ -46,12 +46,15 @@
private final VersionsConfiguration verCfg;
private final SessionImplementor sessionImplementor;
private final Session session;
+ private final FirstLevelCache firstLevelCache;
public VersionsReaderImpl(VersionsConfiguration verCfg, Session session,
SessionImplementor sessionImplementor) {
this.verCfg = verCfg;
this.sessionImplementor = sessionImplementor;
this.session = session;
+
+ firstLevelCache = new FirstLevelCache();
}
private void checkSession() {
@@ -68,6 +71,10 @@
return session;
}
+ public FirstLevelCache getFirstLevelCache() {
+ return firstLevelCache;
+ }
+
@SuppressWarnings({"unchecked"})
public <T> T find(Class<T> cls, Object primaryKey, Number revision)
throws
IllegalArgumentException, NotVersionedException, IllegalStateException {
@@ -83,14 +90,22 @@
throw new NotVersionedException(entityName, entityName + " is not
versioned!");
}
+ if (firstLevelCache.contains(entityName, revision, primaryKey)) {
+ return (T) firstLevelCache.get(entityName, revision, primaryKey);
+ }
+
+ Object result;
try {
- return (T) createQuery().forEntitiesAtRevision(cls, revision)
+ // The result is put into the cache by the entity instantiator called from
the query
+ result = createQuery().forEntitiesAtRevision(cls, revision)
.add(VersionsRestrictions.idEq(primaryKey)).getSingleResult();
} catch (NoResultException e) {
- return null;
+ result = null;
} catch (NonUniqueResultException e) {
throw new VersionsException(e);
}
+
+ return (T) result;
}
@SuppressWarnings({"unchecked"})
Modified: trunk/src/main/org/jboss/envers/reader/VersionsReaderImplementor.java
===================================================================
--- trunk/src/main/org/jboss/envers/reader/VersionsReaderImplementor.java 2008-09-26
15:33:14 UTC (rev 172)
+++ trunk/src/main/org/jboss/envers/reader/VersionsReaderImplementor.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -32,4 +32,5 @@
public interface VersionsReaderImplementor extends VersionsReader {
SessionImplementor getSessionImplementor();
Session getSession();
+ FirstLevelCache getFirstLevelCache();
}
Modified: trunk/src/main/org/jboss/envers/tools/ConcurrentReferenceHashMap.java
===================================================================
--- trunk/src/main/org/jboss/envers/tools/ConcurrentReferenceHashMap.java 2008-09-26
15:33:14 UTC (rev 172)
+++ trunk/src/main/org/jboss/envers/tools/ConcurrentReferenceHashMap.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -263,6 +263,7 @@
static interface KeyReference {
int keyHash();
+ Object keyRef();
}
/**
@@ -270,13 +271,17 @@
*/
static final class WeakKeyReference<K> extends WeakReference<K>
implements KeyReference {
final int hash;
- WeakKeyReference(K key, int hash, ReferenceQueue<K> refQueue) {
+ WeakKeyReference(K key, int hash, ReferenceQueue<Object> refQueue) {
super(key, refQueue);
this.hash = hash;
}
public final int keyHash() {
return hash;
}
+
+ public final Object keyRef() {
+ return this;
+ }
}
/**
@@ -284,15 +289,54 @@
*/
static final class SoftKeyReference<K> extends SoftReference<K>
implements KeyReference {
final int hash;
- SoftKeyReference(K key, int hash, ReferenceQueue<K> refQueue) {
+ SoftKeyReference(K key, int hash, ReferenceQueue<Object> refQueue) {
super(key, refQueue);
this.hash = hash;
}
public final int keyHash() {
return hash;
}
+
+ public final Object keyRef() {
+ return this;
+ }
}
+ static final class WeakValueReference<V> extends WeakReference<V>
implements KeyReference {
+ final Object keyRef;
+ final int hash;
+ WeakValueReference(V value, Object keyRef, int hash, ReferenceQueue<Object>
refQueue) {
+ super(value, refQueue);
+ this.keyRef = keyRef;
+ this.hash = hash;
+ }
+
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return keyRef;
+ }
+ }
+
+ static final class SoftValueReference<V> extends SoftReference<V>
implements KeyReference {
+ final Object keyRef;
+ final int hash;
+ SoftValueReference(V value, Object keyRef, int hash, ReferenceQueue<Object>
refQueue) {
+ super(value, refQueue);
+ this.keyRef = keyRef;
+ this.hash = hash;
+ }
+ public final int keyHash() {
+ return hash;
+ }
+
+ public final Object keyRef() {
+ return keyRef;
+ }
+ }
+
/**
* ConcurrentReferenceHashMap list entry. Note that this is never exported
* out as a user-visible Map.Entry.
@@ -310,45 +354,39 @@
final int hash;
volatile Object valueRef;
final HashEntry<K,V> next;
- final ReferenceType keyType;
- final ReferenceType valueType;
HashEntry(K key, int hash, HashEntry<K,V> next, V value,
ReferenceType keyType, ReferenceType valueType,
- ReferenceQueue<K> refQueue) {
- this.keyType = keyType;
- this.valueType = valueType;
- this.keyRef = newKeyReference(key, hash, refQueue);
+ ReferenceQueue<Object> refQueue) {
this.hash = hash;
this.next = next;
- this.valueRef = newValueReference(value);
+ this.keyRef = newKeyReference(key, keyType, refQueue);
+ this.valueRef = newValueReference(value, valueType, refQueue);
}
- final Object newKeyReference(K key, int hash, ReferenceQueue<K> refQueue)
{
- switch (keyType) {
- case WEAK:
- return new WeakKeyReference<K>(key, hash, refQueue);
- case SOFT:
- return new SoftKeyReference<K>(key, hash, refQueue);
- }
+ final Object newKeyReference(K key, ReferenceType keyType,
+ ReferenceQueue<Object> refQueue) {
+ if (keyType == ReferenceType.WEAK)
+ return new WeakKeyReference<K>(key, hash, refQueue);
+ if (keyType == ReferenceType.SOFT)
+ return new SoftKeyReference<K>(key, hash, refQueue);
return key;
}
- final Object newValueReference(V value) {
- switch (valueType) {
- case WEAK:
- return new WeakReference<V>(value);
- case SOFT:
- return new SoftReference<V>(value);
- }
+ final Object newValueReference(V value, ReferenceType valueType,
+ ReferenceQueue<Object> refQueue) {
+ if (valueType == ReferenceType.WEAK)
+ return new WeakValueReference<V>(value, keyRef, hash, refQueue);
+ if (valueType == ReferenceType.SOFT)
+ return new SoftValueReference<V>(value, keyRef, hash, refQueue);
return value;
}
@SuppressWarnings("unchecked")
final K key() {
- if (keyRef instanceof Reference)
+ if (keyRef instanceof KeyReference)
return ((Reference<K>)keyRef).get();
return (K) keyRef;
@@ -360,14 +398,14 @@
@SuppressWarnings("unchecked")
final V dereferenceValue(Object value) {
- if (value instanceof Reference)
+ if (value instanceof KeyReference)
return ((Reference<V>)value).get();
return (V) value;
}
- final void setValue(V value) {
- this.valueRef = newValueReference(value);
+ final void setValue(V value, ReferenceType valueType,
ReferenceQueue<Object> refQueue) {
+ this.valueRef = newValueReference(value, valueType, refQueue);
}
@SuppressWarnings("unchecked")
@@ -460,7 +498,7 @@
* The collected weak-key reference queue for this segment.
* This should be (re)initialized whenever table is assigned,
*/
- transient volatile ReferenceQueue<K> refQueue;
+ transient volatile ReferenceQueue<Object> refQueue;
final ReferenceType keyType;
@@ -493,7 +531,7 @@
void setTable(HashEntry<K,V>[] newTable) {
threshold = (int)(newTable.length * loadFactor);
table = newTable;
- refQueue = new ReferenceQueue<K>();
+ refQueue = new ReferenceQueue<Object>();
}
/**
@@ -525,7 +563,7 @@
}
}
- /* Specialized implementations of mapToMapFromEntity methods */
+ /* Specialized implementations of map methods */
V get(Object key, int hash) {
if (count != 0) { // read-volatile
@@ -589,7 +627,7 @@
boolean replaced = false;
if (e != null && oldValue.equals(e.value())) {
replaced = true;
- e.setValue(newValue);
+ e.setValue(newValue, valueType, refQueue);
}
return replaced;
} finally {
@@ -608,7 +646,7 @@
V oldValue = null;
if (e != null) {
oldValue = e.value();
- e.setValue(newValue);
+ e.setValue(newValue, valueType, refQueue);
}
return oldValue;
} finally {
@@ -639,7 +677,7 @@
if (e != null) {
oldValue = e.value();
if (!onlyIfAbsent)
- e.setValue(value);
+ e.setValue(value, valueType, refQueue);
}
else {
oldValue = null;
@@ -726,19 +764,19 @@
/**
* Remove; match on key only if value null, else match both.
*/
- V remove(Object key, int hash, Object value, boolean weakRemove) {
+ V remove(Object key, int hash, Object value, boolean refRemove) {
lock();
try {
- if (!weakRemove)
+ if (!refRemove)
removeStale();
int c = count - 1;
HashEntry<K,V>[] tab = table;
int index = hash & (tab.length - 1);
HashEntry<K,V> first = tab[index];
HashEntry<K,V> e = first;
- // a weak remove operation compares the WeakReference instance
- while (e != null && (!weakRemove || key != e.keyRef)
- && (e.hash != hash || !keyEq(key, e.key())))
+ // a ref remove operation compares the Reference instance
+ while (e != null && key != e.keyRef
+ && (refRemove || hash != e.hash || !keyEq(key,
e.key())))
e = e.next;
V oldValue = null;
@@ -771,12 +809,9 @@
}
final void removeStale() {
- if (keyType == ReferenceType.STRONG)
- return;
-
KeyReference ref;
while ((ref = (KeyReference) refQueue.poll()) != null) {
- remove(ref, ref.keyHash(), null, true);
+ remove(ref.keyRef(), ref.keyHash(), null, true);
}
}
@@ -789,7 +824,7 @@
tab[i] = null;
++modCount;
// replace the reference queue to avoid unnecessary stale cleanups
- refQueue = new ReferenceQueue<K>();
+ refQueue = new ReferenceQueue<Object>();
count = 0; // write-volatile
} finally {
unlock();
Modified: trunk/src/main/org/jboss/envers/tools/Tools.java
===================================================================
--- trunk/src/main/org/jboss/envers/tools/Tools.java 2008-09-26 15:33:14 UTC (rev 172)
+++ trunk/src/main/org/jboss/envers/tools/Tools.java 2008-10-01 10:26:59 UTC (rev 173)
@@ -21,14 +21,16 @@
*/
package org.jboss.envers.tools;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.*;
/**
* @author Adam Warski (adam at warski dot org)
*/
public class Tools {
+ public static <K,V> Map<K,V> newHashMap() {
+ return new HashMap<K,V>();
+ }
+
public static boolean objectsEqual(Object obj1, Object obj2) {
if (obj1 == null) {
return obj2 == null;
Copied: trunk/src/test/org/jboss/envers/test/integration/cache/OneToManyCache.java (from
rev 148, trunk/src/test/org/jboss/envers/test/integration/onetomany/BasicSet.java)
===================================================================
--- trunk/src/test/org/jboss/envers/test/integration/cache/OneToManyCache.java
(rev 0)
+++ trunk/src/test/org/jboss/envers/test/integration/cache/OneToManyCache.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -0,0 +1,120 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.integration.AbstractEntityTest;
+import org.jboss.envers.test.entities.onetomany.SetRefEdEntity;
+import org.jboss.envers.test.entities.onetomany.SetRefIngEntity;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.hibernate.ejb.Ejb3Configuration;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+@SuppressWarnings({"ObjectEquality"})
+public class OneToManyCache extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+ private Integer ing2_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(SetRefEdEntity.class);
+ cfg.addAnnotatedClass(SetRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ EntityManager em = getEntityManager();
+
+ SetRefEdEntity ed1 = new SetRefEdEntity(1, "data_ed_1");
+ SetRefEdEntity ed2 = new SetRefEdEntity(2, "data_ed_2");
+
+ SetRefIngEntity ing1 = new SetRefIngEntity(1, "data_ing_1");
+ SetRefIngEntity ing2 = new SetRefIngEntity(2, "data_ing_2");
+
+ // Revision 1
+ em.getTransaction().begin();
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ ing1.setReference(ed1);
+ ing2.setReference(ed1);
+
+ em.persist(ing1);
+ em.persist(ing2);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(SetRefIngEntity.class, ing1.getId());
+ ing2 = em.find(SetRefIngEntity.class, ing2.getId());
+ ed2 = em.find(SetRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+ ing2.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ ing2_id = ing2.getId();
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFind() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id,
1);
+
+ SetRefIngEntity ing1_rev1 = getVersionsReader().find(SetRefIngEntity.class,
ing1_id, 1);
+ SetRefIngEntity ing2_rev1 = getVersionsReader().find(SetRefIngEntity.class,
ing2_id, 1);
+
+ // It should be exactly the same object
+ assert ing1_rev1.getReference() == ed1_rev1;
+ assert ing2_rev1.getReference() == ed1_rev1;
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterCollectionAccessRev1() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id,
1);
+
+ // It should be exactly the same object
+ assert ed1_rev1.getReffering().size() == 2;
+ for (SetRefIngEntity setRefIngEntity : ed1_rev1.getReffering()) {
+ assert setRefIngEntity.getReference() == ed1_rev1;
+ }
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterCollectionAccessRev2() {
+ SetRefEdEntity ed2_rev2 = getVersionsReader().find(SetRefEdEntity.class, ed2_id,
2);
+
+ assert ed2_rev2.getReffering().size() == 2;
+ for (SetRefIngEntity setRefIngEntity : ed2_rev2.getReffering()) {
+ assert setRefIngEntity.getReference() == ed2_rev2;
+ }
+ }
+
+ @Test
+ public void testCacheFindAfterCollectionAccessRev1() {
+ SetRefEdEntity ed1_rev1 = getVersionsReader().find(SetRefEdEntity.class, ed1_id,
1);
+
+ // Reading the collection
+ assert ed1_rev1.getReffering().size() == 2;
+
+ SetRefIngEntity ing1_rev1 = getVersionsReader().find(SetRefIngEntity.class,
ing1_id, 1);
+ SetRefIngEntity ing2_rev1 = getVersionsReader().find(SetRefIngEntity.class,
ing2_id, 1);
+
+ for (SetRefIngEntity setRefIngEntity : ed1_rev1.getReffering()) {
+ assert setRefIngEntity == ing1_rev1 || setRefIngEntity == ing2_rev1;
+ }
+ }
+}
\ No newline at end of file
Property changes on:
trunk/src/test/org/jboss/envers/test/integration/cache/OneToManyCache.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/src/test/org/jboss/envers/test/integration/cache/OneToOneCache.java (from
rev 148,
trunk/src/test/org/jboss/envers/test/integration/onetoone/bidirectional/Bidirectional.java)
===================================================================
--- trunk/src/test/org/jboss/envers/test/integration/cache/OneToOneCache.java
(rev 0)
+++ trunk/src/test/org/jboss/envers/test/integration/cache/OneToOneCache.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -0,0 +1,80 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.integration.AbstractEntityTest;
+import org.jboss.envers.test.integration.onetoone.bidirectional.BiRefEdEntity;
+import org.jboss.envers.test.integration.onetoone.bidirectional.BiRefIngEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+@SuppressWarnings({"ObjectEquality"})
+public class OneToOneCache extends AbstractEntityTest {
+ private Integer ed1_id;
+ private Integer ed2_id;
+
+ private Integer ing1_id;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(BiRefEdEntity.class);
+ cfg.addAnnotatedClass(BiRefIngEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ BiRefEdEntity ed1 = new BiRefEdEntity(1, "data_ed_1");
+ BiRefEdEntity ed2 = new BiRefEdEntity(2, "data_ed_2");
+
+ BiRefIngEntity ing1 = new BiRefIngEntity(3, "data_ing_1");
+
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+
+ ing1.setReference(ed1);
+
+ em.persist(ed1);
+ em.persist(ed2);
+
+ em.persist(ing1);
+
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+
+ ing1 = em.find(BiRefIngEntity.class, ing1.getId());
+ ed2 = em.find(BiRefEdEntity.class, ed2.getId());
+
+ ing1.setReference(ed2);
+
+ em.getTransaction().commit();
+
+ //
+
+ ed1_id = ed1.getId();
+ ed2_id = ed2.getId();
+
+ ing1_id = ing1.getId();
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFindRev1() {
+ BiRefEdEntity ed1_rev1 = getVersionsReader().find(BiRefEdEntity.class, ed1_id,
1);
+ BiRefIngEntity ing1_rev1 = getVersionsReader().find(BiRefIngEntity.class,
ing1_id, 1);
+
+ assert ing1_rev1.getReference() == ed1_rev1;
+ }
+
+ @Test
+ public void testCacheReferenceAccessAfterFindRev2() {
+ BiRefEdEntity ed2_rev2 = getVersionsReader().find(BiRefEdEntity.class, ed2_id,
2);
+ BiRefIngEntity ing1_rev2 = getVersionsReader().find(BiRefIngEntity.class,
ing1_id, 2);
+
+ assert ing1_rev2.getReference() == ed2_rev2;
+ }
+}
\ No newline at end of file
Property changes on:
trunk/src/test/org/jboss/envers/test/integration/cache/OneToOneCache.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/src/test/org/jboss/envers/test/integration/cache/QueryCache.java (from rev
148, trunk/src/test/org/jboss/envers/test/integration/basic/Simple.java)
===================================================================
--- trunk/src/test/org/jboss/envers/test/integration/cache/QueryCache.java
(rev 0)
+++ trunk/src/test/org/jboss/envers/test/integration/cache/QueryCache.java 2008-10-01
10:26:59 UTC (rev 173)
@@ -0,0 +1,63 @@
+package org.jboss.envers.test.integration.cache;
+
+import org.jboss.envers.test.integration.AbstractEntityTest;
+import org.jboss.envers.test.entities.IntTestEntity;
+import org.hibernate.ejb.Ejb3Configuration;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeClass;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+/**
+ * @author Adam Warski (adam at warski dot org)
+ */
+@SuppressWarnings({"ObjectEquality"})
+public class QueryCache extends AbstractEntityTest {
+ private Integer id1;
+
+ public void configure(Ejb3Configuration cfg) {
+ cfg.addAnnotatedClass(IntTestEntity.class);
+ }
+
+ @BeforeClass(dependsOnMethods = "init")
+ public void initData() {
+ // Revision 1
+ EntityManager em = getEntityManager();
+ em.getTransaction().begin();
+ IntTestEntity ite = new IntTestEntity(10);
+ em.persist(ite);
+ id1 = ite.getId();
+ em.getTransaction().commit();
+
+ // Revision 2
+ em.getTransaction().begin();
+ ite = em.find(IntTestEntity.class, id1);
+ ite.setNumber(20);
+ em.getTransaction().commit();
+ }
+
+ @Test
+ public void testCacheFindAfterRevisionsOfEntityQuery() {
+ List entsFromQuery = getVersionsReader().createQuery()
+ .forRevisionsOfEntity(IntTestEntity.class, true, false)
+ .getResultList();
+
+ IntTestEntity entFromFindRev1 = getVersionsReader().find(IntTestEntity.class,
id1, 1);
+ IntTestEntity entFromFindRev2 = getVersionsReader().find(IntTestEntity.class,
id1, 2);
+
+ assert entFromFindRev1 == entsFromQuery.get(0);
+ assert entFromFindRev2 == entsFromQuery.get(1);
+ }
+
+ @Test
+ public void testCacheFindAfterEntitiesAtRevisionQuery() {
+ IntTestEntity entFromQuery = (IntTestEntity) getVersionsReader().createQuery()
+ .forEntitiesAtRevision(IntTestEntity.class, 1)
+ .getSingleResult();
+
+ IntTestEntity entFromFind = getVersionsReader().find(IntTestEntity.class, id1,
1);
+
+ assert entFromFind == entFromQuery;
+ }
+}
\ No newline at end of file
Property changes on:
trunk/src/test/org/jboss/envers/test/integration/cache/QueryCache.java
___________________________________________________________________
Name: svn:mergeinfo
+