HHH-10770 JCache provider updates
* Steer away from EntryProcessor * Add tests
This commit is contained in:
parent
a872885a43
commit
2ddefd615b
|
@ -12,6 +12,7 @@ import org.jboss.logging.annotations.MessageLogger;
|
||||||
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
|
||||||
|
import static org.jboss.logging.Logger.Level.ERROR;
|
||||||
import static org.jboss.logging.Logger.Level.WARN;
|
import static org.jboss.logging.Logger.Level.WARN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,4 +37,12 @@ public interface JCacheMessageLogger extends CoreMessageLogger {
|
||||||
id = NAMESPACE + 2
|
id = NAMESPACE + 2
|
||||||
)
|
)
|
||||||
void attemptToRestopAlreadyStoppedJCacheProvider();
|
void attemptToRestopAlreadyStoppedJCacheProvider();
|
||||||
|
|
||||||
|
@LogMessage(level = ERROR)
|
||||||
|
@Message(
|
||||||
|
value = "Cache: %s Key: %s Lockable: %s. A soft-locked cache entry was missing. This is either"
|
||||||
|
+ " out of balance lock/unlock sequences, or an eagerly evicting cache.",
|
||||||
|
id = NAMESPACE + 3
|
||||||
|
)
|
||||||
|
void missingLock(JCacheRegion region, Object key, Object value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.time.Timestamper;
|
||||||
import org.hibernate.cache.spi.CacheDataDescription;
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
import org.hibernate.cache.spi.CollectionRegion;
|
import org.hibernate.cache.spi.CollectionRegion;
|
||||||
import org.hibernate.cache.spi.EntityRegion;
|
import org.hibernate.cache.spi.EntityRegion;
|
||||||
|
@ -187,11 +188,11 @@ public class JCacheRegionFactory implements RegionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
static long nextTS() {
|
static long nextTS() {
|
||||||
return System.currentTimeMillis() / 100;
|
return Timestamper.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int timeOut() {
|
static int timeOut() {
|
||||||
return (int) (TimeUnit.SECONDS.toMillis(60) / 100);
|
return (int) TimeUnit.SECONDS.toMillis( 60 ) * Timestamper.ONE_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getProp(Properties properties, String prop) {
|
private String getProp(Properties properties, String prop) {
|
||||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.cache.jcache;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.cache.Cache;
|
import javax.cache.Cache;
|
||||||
import javax.cache.processor.EntryProcessor;
|
|
||||||
|
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.cache.spi.CacheDataDescription;
|
import org.hibernate.cache.spi.CacheDataDescription;
|
||||||
|
@ -33,17 +32,19 @@ public class JCacheTransactionalDataRegion extends JCacheRegion implements Trans
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isTransactionAware() {
|
public boolean isTransactionAware() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CacheDataDescription getCacheDataDescription() {
|
public CacheDataDescription getCacheDataDescription() {
|
||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void throwIfAccessTypeUnsupported(AccessType accessType) {
|
protected void throwIfAccessTypeUnsupported(AccessType accessType) {
|
||||||
if ( supportedAccessTypes().contains( accessType ) ) {
|
if ( !supportedAccessTypes().contains( accessType ) ) {
|
||||||
throw new UnsupportedOperationException( "This doesn't JCacheTransactionalDataRegion doesn't support " + accessType );
|
throw new UnsupportedOperationException( "JCacheTransactionalDataRegion doesn't support " + accessType );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +68,15 @@ public class JCacheTransactionalDataRegion extends JCacheRegion implements Trans
|
||||||
cache.put( key, value );
|
cache.put( key, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean putIfAbsent(Object key, Object value) {
|
||||||
|
return cache.putIfAbsent( key, value );
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean replace(Object key, Object expected, Object value) {
|
||||||
|
return cache.replace( key, expected, value );
|
||||||
|
}
|
||||||
|
|
||||||
public SessionFactoryOptions getSessionFactoryOptions() {
|
public SessionFactoryOptions getSessionFactoryOptions() {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T invoke(Object key, EntryProcessor<Object, Object, T> entryProcessor, Object... args) {
|
|
||||||
return cache.invoke( key, entryProcessor, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,23 +11,29 @@ import java.io.Serializable;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import javax.cache.processor.EntryProcessor;
|
|
||||||
import javax.cache.processor.EntryProcessorException;
|
|
||||||
import javax.cache.processor.MutableEntry;
|
|
||||||
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
|
import org.hibernate.cache.jcache.JCacheMessageLogger;
|
||||||
import org.hibernate.cache.jcache.JCacheTransactionalDataRegion;
|
import org.hibernate.cache.jcache.JCacheTransactionalDataRegion;
|
||||||
import org.hibernate.cache.spi.access.SoftLock;
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alex Snaps
|
* @author Alex Snaps
|
||||||
*/
|
*/
|
||||||
public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactionalDataRegion> {
|
abstract class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactionalDataRegion> {
|
||||||
|
|
||||||
|
private static final JCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
JCacheMessageLogger.class,
|
||||||
|
AbstractReadWriteRegionAccessStrategy.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
protected final R region;
|
protected final R region;
|
||||||
protected final Comparator versionComparator;
|
protected final Comparator versionComparator;
|
||||||
private final UUID uuid = UUID.randomUUID();
|
private final UUID uuid = UUID.randomUUID();
|
||||||
private final AtomicLong nextLockId = new AtomicLong();
|
private final AtomicLong nextLockId = new AtomicLong();
|
||||||
|
private final AtomicLong nextItemId = new AtomicLong();
|
||||||
|
|
||||||
public AbstractReadWriteRegionAccessStrategy(R region) {
|
public AbstractReadWriteRegionAccessStrategy(R region) {
|
||||||
this.versionComparator = region.getCacheDataDescription().getVersionComparator();
|
this.versionComparator = region.getCacheDataDescription().getVersionComparator();
|
||||||
|
@ -51,26 +57,29 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version) throws CacheException {
|
||||||
return region.invoke(
|
while (true) {
|
||||||
key, new EntryProcessor<Object, Object, Boolean>() {
|
Lockable item = (Lockable) region.get( key );
|
||||||
@Override
|
|
||||||
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
if (item == null) {
|
||||||
throws EntryProcessorException {
|
/*
|
||||||
final Lockable item = (Lockable) entry.getValue();
|
* If the item is null due a softlock being evicted... then this
|
||||||
final boolean writeable = item == null || item.isWriteable(
|
* is wrong, the in-doubt soft-lock could get replaced with the
|
||||||
(Long) args[1],
|
* old value. All that can be done from a JCache perspective is
|
||||||
args[2],
|
* to log a warning.
|
||||||
versionComparator
|
*/
|
||||||
);
|
if (region.putIfAbsent( key, new Item( value, version, txTimestamp, nextItemId() ))) {
|
||||||
if ( writeable ) {
|
return true;
|
||||||
entry.setValue( new Item( args[0], args[2], region.nextTimestamp() ) );
|
}
|
||||||
return true;
|
}
|
||||||
}
|
else if (item.isWriteable( txTimestamp, version, versionComparator )) {
|
||||||
else {
|
if (region.replace( key, item, new Item( value, version, txTimestamp, nextItemId() ))) {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, value, txTimestamp, version);
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
public boolean putFromLoad(SharedSessionContractImplementor session, Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||||
|
@ -79,49 +88,47 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException {
|
public SoftLock lockItem(SharedSessionContractImplementor session, Object key, Object version) throws CacheException {
|
||||||
return region.invoke(
|
long timeout = region.nextTimestamp() + region.getTimeout();
|
||||||
key, new EntryProcessor<Object, Object, SoftLock>() {
|
while (true) {
|
||||||
@Override
|
Lockable item = (Lockable) region.get( key );
|
||||||
public SoftLock process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
if ( item == null ) {
|
||||||
final Lockable item = (Lockable) entry.getValue();
|
/*
|
||||||
final long timeout = region.nextTimestamp() + region.getTimeout();
|
* What happens here if a previous soft-lock was evicted to make
|
||||||
final Lock lock = ( item == null ) ? new Lock(
|
* this null.
|
||||||
timeout,
|
*/
|
||||||
(UUID) args[0],
|
Lock lock = new Lock(timeout, uuid, nextLockId(), version);
|
||||||
(Long) args[1],
|
if (region.putIfAbsent( key, lock )) {
|
||||||
args[2]
|
return lock;
|
||||||
)
|
}
|
||||||
: item.lock( timeout, (UUID) args[0], (Long) args[1] );
|
}
|
||||||
entry.setValue( lock );
|
else {
|
||||||
return lock;
|
Lock lock = item.lock( timeout, uuid, nextLockId() );
|
||||||
}
|
if (region.replace(key, item, lock)) {
|
||||||
}, uuid, nextLockId(), version
|
return lock;
|
||||||
);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException {
|
public void unlockItem(SharedSessionContractImplementor session, Object key, SoftLock lock) throws CacheException {
|
||||||
region.invoke(
|
while (true) {
|
||||||
key, new EntryProcessor<Object, Object, Void>() {
|
Lockable item = (Lockable) region.get( key );
|
||||||
@Override
|
|
||||||
public Void process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
|
||||||
final Lockable item = (Lockable) entry.getValue();
|
|
||||||
|
|
||||||
if ( (item != null) && item.isUnlockable( (SoftLock) args[0] ) ) {
|
if (item != null && item.isUnlockable( lock )) {
|
||||||
( (Lock) item ).unlock( region.nextTimestamp() );
|
if (region.replace(key, item, ((Lock) item ).unlock(region.nextTimestamp()))) {
|
||||||
entry.setValue( item );
|
return;
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
entry.setValue( null );
|
else {
|
||||||
}
|
handleMissingLock( key, item );
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
}, lock);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
region.remove( key );
|
//this access strategy is asynchronous
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAll() throws CacheException {
|
public void removeAll() throws CacheException {
|
||||||
|
@ -141,13 +148,25 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||||
throw new UnsupportedOperationException( "JCache doesn't support region locking" );
|
region.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long nextLockId() {
|
private long nextLockId() {
|
||||||
return nextLockId.getAndIncrement();
|
return nextLockId.getAndIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected long nextItemId() {
|
||||||
|
return nextItemId.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleMissingLock(Object key, Lockable lock) {
|
||||||
|
LOG.missingLock( region, key, lock );
|
||||||
|
long ts = region.nextTimestamp() + region.getTimeout();
|
||||||
|
// create new lock that times out immediately
|
||||||
|
Lock newLock = new Lock( ts, uuid, nextLockId.getAndIncrement(), null ).unlock( ts );
|
||||||
|
region.put( key, newLock );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface type implemented by all wrapper objects in the cache.
|
* Interface type implemented by all wrapper objects in the cache.
|
||||||
*/
|
*/
|
||||||
|
@ -189,14 +208,16 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
private final Object value;
|
private final Object value;
|
||||||
private final Object version;
|
private final Object version;
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
|
private final long itemId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
||||||
*/
|
*/
|
||||||
Item(Object value, Object version, long timestamp) {
|
Item(Object value, Object version, long timestamp, long itemId) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
|
this.itemId = itemId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -224,6 +245,29 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||||
return new Lock( timeout, uuid, lockId, version );
|
return new Lock( timeout, uuid, lockId, version );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (obj instanceof Item) {
|
||||||
|
return itemId == ((Item) obj).itemId;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Long.hashCode( itemId );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return value.toString() + " version: " + version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -236,19 +280,28 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
private final long lockId;
|
private final long lockId;
|
||||||
private final Object version;
|
private final Object version;
|
||||||
|
|
||||||
private long timeout;
|
private final long timeout;
|
||||||
private boolean concurrent;
|
private final boolean concurrent;
|
||||||
private int multiplicity = 1;
|
private final int multiplicity;
|
||||||
private long unlockTimestamp;
|
private final long unlockTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a locked item with the given identifiers and object version.
|
* Creates a locked item with the given identifiers and object version.
|
||||||
*/
|
*/
|
||||||
public Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
public Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
||||||
this.timeout = timeout;
|
this(timeout, sourceUuid, lockId, version, 0, 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Lock(long timeout, UUID sourceUuid, long lockId, Object version,
|
||||||
|
long unlockTimestamp, int multiplicity, boolean concurrent) {
|
||||||
|
this.sourceUuid = sourceUuid;
|
||||||
this.lockId = lockId;
|
this.lockId = lockId;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.sourceUuid = sourceUuid;
|
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.unlockTimestamp = unlockTimestamp;
|
||||||
|
this.multiplicity = multiplicity;
|
||||||
|
this.concurrent = concurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -279,7 +332,15 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUnlockable(SoftLock lock) {
|
public boolean isUnlockable(SoftLock lock) {
|
||||||
return equals( lock );
|
if ( lock == this ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if ( lock instanceof Lock ) {
|
||||||
|
return (lockId == ((Lock) lock).lockId) && sourceUuid.equals(((Lock) lock).sourceUuid);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -289,7 +350,8 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ( o instanceof Lock ) {
|
else if ( o instanceof Lock ) {
|
||||||
return ( lockId == ( (Lock) o ).lockId ) && sourceUuid.equals( ( (Lock) o ).sourceUuid );
|
return (lockId == ((Lock)o ).lockId) && sourceUuid.equals( ( (Lock) o ).sourceUuid )
|
||||||
|
&& (multiplicity == ((Lock) o).multiplicity);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -299,11 +361,7 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
final int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
||||||
int temp = (int) lockId;
|
return hash ^ Long.hashCode( lockId );
|
||||||
for ( int i = 1; i < Long.SIZE / Integer.SIZE; i++ ) {
|
|
||||||
temp ^= ( lockId >>> ( i * Integer.SIZE ) );
|
|
||||||
}
|
|
||||||
return hash + temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -315,18 +373,22 @@ public class AbstractReadWriteRegionAccessStrategy<R extends JCacheTransactional
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||||
concurrent = true;
|
return new Lock( timeout, this.sourceUuid, this.lockId, this.version,
|
||||||
multiplicity++;
|
0, this.multiplicity + 1, true );
|
||||||
this.timeout = timeout;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlocks this Lock, and timestamps the unlock event.
|
* Unlocks this Lock, and timestamps the unlock event.
|
||||||
*/
|
*/
|
||||||
public void unlock(long timestamp) {
|
public Lock unlock(long timestamp) {
|
||||||
if ( --multiplicity == 0 ) {
|
if (multiplicity == 1) {
|
||||||
unlockTimestamp = timestamp;
|
return new Lock(timeout, sourceUuid, lockId, version,
|
||||||
|
timestamp, 0, concurrent );
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Lock(timeout, sourceUuid, lockId, version,
|
||||||
|
0, multiplicity - 1, concurrent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,17 +68,17 @@ abstract class JCacheRegionAccessStrategy<R extends JCacheTransactionalDataRegio
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unlockRegion(SoftLock lock) throws CacheException {
|
public void unlockRegion(SoftLock lock) throws CacheException {
|
||||||
// no op
|
evictAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
region.remove( key );
|
// jcache only supports asynchronous access strategies
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAll() throws CacheException {
|
public void removeAll() throws CacheException {
|
||||||
region.clear();
|
evictAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
|
|
||||||
package org.hibernate.cache.jcache.access;
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
import org.hibernate.cache.jcache.JCacheCollectionRegion;
|
import org.hibernate.cache.jcache.JCacheCollectionRegion;
|
||||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
import org.hibernate.persister.collection.CollectionPersister;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,4 +36,9 @@ public class NonStrictCollectionRegionAccessStrategy
|
||||||
return DefaultCacheKeysFactory.getCollectionId( cacheKey );
|
return DefaultCacheKeysFactory.getCollectionId( cacheKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
|
evict( key );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,4 +60,9 @@ public class NonStrictEntityRegionAccessStrategy extends JCacheRegionAccessStrat
|
||||||
public Object getCacheKeyId(Object cacheKey) {
|
public Object getCacheKeyId(Object cacheKey) {
|
||||||
return DefaultCacheKeysFactory.getEntityId( cacheKey );
|
return DefaultCacheKeysFactory.getEntityId( cacheKey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(SharedSessionContractImplementor session, Object key) throws CacheException {
|
||||||
|
evict( key );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cache.jcache.access;
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
import javax.cache.processor.EntryProcessor;
|
|
||||||
import javax.cache.processor.EntryProcessorException;
|
|
||||||
import javax.cache.processor.MutableEntry;
|
|
||||||
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
import org.hibernate.cache.jcache.JCacheEntityRegion;
|
import org.hibernate.cache.jcache.JCacheEntityRegion;
|
||||||
|
@ -38,21 +34,7 @@ public class ReadWriteEntityRegionAccessStrategy
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value, Object version) throws CacheException {
|
||||||
return region.invoke(
|
return region.putIfAbsent( key, new Item(value, version, region.nextTimestamp(), nextItemId() ));
|
||||||
key, new EntryProcessor<Object, Object, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
|
||||||
if ( !entry.exists() ) {
|
|
||||||
entry.setValue( new Item( args[0], args[1], (Long) args[2] ) );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, value, version, region.nextTimestamp()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,33 +46,28 @@ public class ReadWriteEntityRegionAccessStrategy
|
||||||
@Override
|
@Override
|
||||||
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
|
||||||
throws CacheException {
|
throws CacheException {
|
||||||
return region.invoke(
|
while (true) {
|
||||||
key, new EntryProcessor<Object, Object, Boolean>() {
|
Lockable item = (Lockable) region.get( key );
|
||||||
@Override
|
|
||||||
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
|
||||||
final Lockable item = (Lockable) entry.getValue();
|
|
||||||
|
|
||||||
if ( item != null && item.isUnlockable( (SoftLock) args[3] ) ) {
|
|
||||||
final Lock lockItem = (Lock) item;
|
|
||||||
if ( lockItem.wasLockedConcurrently() ) {
|
|
||||||
lockItem.unlock( (Long) args[1] );
|
|
||||||
entry.setValue( lockItem );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.setValue( new Item( args[0], args[1], (Long) args[4] ) );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.setValue( null );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( item != null && item.isUnlockable( lock ) ) {
|
||||||
|
Lock lockItem = (Lock) item;
|
||||||
|
if ( lockItem.wasLockedConcurrently() ) {
|
||||||
|
if (region.replace( key, lockItem, lockItem.unlock( region.nextTimestamp() ))) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}, value, currentVersion, previousVersion, lock, region.nextTimestamp()
|
}
|
||||||
);
|
else {
|
||||||
|
if (region.replace( key, lockItem, new Item(value, currentVersion, region.nextTimestamp(), nextItemId() ))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleMissingLock( key, item );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,10 +7,6 @@
|
||||||
|
|
||||||
package org.hibernate.cache.jcache.access;
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
import javax.cache.processor.EntryProcessor;
|
|
||||||
import javax.cache.processor.EntryProcessorException;
|
|
||||||
import javax.cache.processor.MutableEntry;
|
|
||||||
|
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
import org.hibernate.cache.jcache.JCacheNaturalIdRegion;
|
import org.hibernate.cache.jcache.JCacheNaturalIdRegion;
|
||||||
|
@ -37,21 +33,7 @@ public class ReadWriteNaturalIdRegionAccessStrategy
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
public boolean afterInsert(SharedSessionContractImplementor session, Object key, Object value) throws CacheException {
|
||||||
return region.invoke(
|
return region.putIfAbsent( key, new Item( value, null, region.nextTimestamp(), nextItemId() ));
|
||||||
key, new EntryProcessor<Object, Object, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
|
||||||
if ( !entry.exists() ) {
|
|
||||||
entry.setValue( new Item( args[0], null, (Long) args[1] ) );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, value, region.nextTimestamp()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,33 +45,28 @@ public class ReadWriteNaturalIdRegionAccessStrategy
|
||||||
@Override
|
@Override
|
||||||
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock)
|
public boolean afterUpdate(SharedSessionContractImplementor session, Object key, Object value, SoftLock lock)
|
||||||
throws CacheException {
|
throws CacheException {
|
||||||
return region.invoke(
|
while (true) {
|
||||||
key, new EntryProcessor<Object, Object, Boolean>() {
|
Lockable item = (Lockable) region.get( key );
|
||||||
@Override
|
|
||||||
public Boolean process(MutableEntry<Object, Object> entry, Object... args)
|
|
||||||
throws EntryProcessorException {
|
|
||||||
final Lockable item = (Lockable) entry.getValue();
|
|
||||||
|
|
||||||
if ( item != null && item.isUnlockable( (SoftLock) args[1] ) ) {
|
|
||||||
final Lock lockItem = (Lock) item;
|
|
||||||
if ( lockItem.wasLockedConcurrently() ) {
|
|
||||||
lockItem.unlock( region.nextTimestamp() );
|
|
||||||
entry.setValue( lockItem );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.setValue( new Item( args[0], null, (Long) args[2] ) );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry.setValue( null );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if ( item != null && item.isUnlockable( lock ) ) {
|
||||||
|
final Lock lockItem = (Lock) item;
|
||||||
|
if ( lockItem.wasLockedConcurrently() ) {
|
||||||
|
if (region.replace( key, lockItem, lockItem.unlock( region.nextTimestamp() ) )) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}, value, lock, region.nextTimestamp()
|
}
|
||||||
);
|
else {
|
||||||
|
if (region.replace( key, lockItem, new Item(value, null, region.nextTimestamp(), nextItemId() ))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
handleMissingLock( key, item );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
41
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/time/Timestamper.java
vendored
Normal file
41
hibernate-jcache/src/main/java/org/hibernate/cache/jcache/time/Timestamper.java
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.time;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates increasing identifiers (in a single VM only). Not valid across multiple VMs. Identifiers are not
|
||||||
|
* necessarily strictly increasing, but usually are.
|
||||||
|
* <p/>
|
||||||
|
* Core while loop implemented by Alex Snaps - EHCache project - under ASL 2.0
|
||||||
|
*
|
||||||
|
* @author Hibernate team
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public final class Timestamper {
|
||||||
|
private static final int BIN_DIGITS = 12;
|
||||||
|
public static final short ONE_MS = 1 << BIN_DIGITS;
|
||||||
|
private static final AtomicLong VALUE = new AtomicLong();
|
||||||
|
|
||||||
|
public static long next() {
|
||||||
|
while ( true ) {
|
||||||
|
long base = System.currentTimeMillis() << BIN_DIGITS;
|
||||||
|
long maxValue = base + ONE_MS - 1;
|
||||||
|
|
||||||
|
for ( long current = VALUE.get(), update = Math.max( base, current + 1 ); update < maxValue;
|
||||||
|
current = VALUE.get(), update = Math.max( base, current + 1 ) ) {
|
||||||
|
if ( VALUE.compareAndSet( current, update ) ) {
|
||||||
|
return update;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Timestamper() {
|
||||||
|
}
|
||||||
|
}
|
32
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/access/ItemValueExtractor.java
vendored
Normal file
32
hibernate-jcache/src/test/java/org/hibernate/cache/jcache/access/ItemValueExtractor.java
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.cache.jcache.access;
|
||||||
|
|
||||||
|
import org.hibernate.cache.jcache.JCacheTransactionalDataRegion;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alex Snaps
|
||||||
|
*/
|
||||||
|
public class ItemValueExtractor extends AbstractReadWriteRegionAccessStrategy<JCacheTransactionalDataRegion> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a read/write cache access strategy around the given cache region.
|
||||||
|
*/
|
||||||
|
public ItemValueExtractor(JCacheTransactionalDataRegion region) {
|
||||||
|
super(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static <T> T getValue(final Object entry) {
|
||||||
|
if(!(entry instanceof Item)) {
|
||||||
|
throw new IllegalArgumentException("Entry needs to be of type " + Item.class.getName());
|
||||||
|
}
|
||||||
|
return (T)((Item)entry).getValue();
|
||||||
|
}
|
||||||
|
}
|
248
hibernate-jcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java
vendored
Normal file
248
hibernate-jcache/src/test/java/org/hibernate/test/cache/HibernateCacheTest.java
vendored
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.cache;
|
||||||
|
|
||||||
|
import org.hibernate.cache.jcache.access.ItemValueExtractor;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cache.spi.access.SoftLock;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.stat.QueryStatistics;
|
||||||
|
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||||
|
import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.domain.Event;
|
||||||
|
import org.hibernate.test.domain.EventManager;
|
||||||
|
import org.hibernate.test.domain.Item;
|
||||||
|
import org.hibernate.test.domain.Person;
|
||||||
|
import org.hibernate.test.domain.PhoneNumber;
|
||||||
|
import org.hibernate.test.domain.VersionedItem;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Dennis
|
||||||
|
* @author Brett Meyer
|
||||||
|
*/
|
||||||
|
public class HibernateCacheTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private static final String REGION_PREFIX = "hibernate.test.";
|
||||||
|
|
||||||
|
public HibernateCacheTest() {
|
||||||
|
System.setProperty( "derby.system.home", "target/derby" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
super.addSettings( settings );
|
||||||
|
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||||
|
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||||
|
ssrb.configure( "hibernate-config/hibernate.cfg.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQueryCacheInvalidation() throws Exception {
|
||||||
|
Session s = sessionFactory().openSession();
|
||||||
|
Transaction t = s.beginTransaction();
|
||||||
|
Item i = new Item();
|
||||||
|
i.setName( "widget" );
|
||||||
|
i.setDescription( "A really top-quality, full-featured widget." );
|
||||||
|
s.persist( i );
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
SecondLevelCacheStatistics slcs = sessionFactory()
|
||||||
|
.getStatistics()
|
||||||
|
.getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() );
|
||||||
|
|
||||||
|
assertThat( slcs.getPutCount(), equalTo( 1L ) );
|
||||||
|
assertThat( slcs.getEntries().size(), equalTo( 1 ) );
|
||||||
|
|
||||||
|
s = sessionFactory().openSession();
|
||||||
|
t = s.beginTransaction();
|
||||||
|
i = (Item) s.get( Item.class, i.getId() );
|
||||||
|
|
||||||
|
assertThat( slcs.getHitCount(), equalTo( 1L ) );
|
||||||
|
assertThat( slcs.getMissCount(), equalTo( 0L ) );
|
||||||
|
|
||||||
|
i.setDescription( "A bog standard item" );
|
||||||
|
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertThat( slcs.getPutCount(), equalTo( 2L ) );
|
||||||
|
|
||||||
|
Object entry = slcs.getEntries().get( i.getId() );
|
||||||
|
Map map;
|
||||||
|
if ( entry instanceof Map ) {
|
||||||
|
map = (Map) entry;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map = ItemValueExtractor.getValue( entry );
|
||||||
|
}
|
||||||
|
assertThat( (String) map.get( "description" ), equalTo( "A bog standard item" ) );
|
||||||
|
assertThat( (String) map.get( "name" ), equalTo( "widget" ) );
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
s = sessionFactory().openSession();
|
||||||
|
t = s.beginTransaction();
|
||||||
|
s.delete( i );
|
||||||
|
t.commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptySecondLevelCacheEntry() throws Exception {
|
||||||
|
sessionFactory().getCache().evictEntityRegion( Item.class.getName() );
|
||||||
|
Statistics stats = sessionFactory().getStatistics();
|
||||||
|
stats.clear();
|
||||||
|
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() );
|
||||||
|
Map cacheEntries = statistics.getEntries();
|
||||||
|
assertThat( cacheEntries.size(), equalTo( 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStaleWritesLeaveCacheConsistent() {
|
||||||
|
Session s = sessionFactory().openSession();
|
||||||
|
Transaction txn = s.beginTransaction();
|
||||||
|
VersionedItem item = new VersionedItem();
|
||||||
|
item.setName( "steve" );
|
||||||
|
item.setDescription( "steve's item" );
|
||||||
|
s.save( item );
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Long initialVersion = item.getVersion();
|
||||||
|
|
||||||
|
// manually revert the version property
|
||||||
|
item.setVersion( item.getVersion() - 1 );
|
||||||
|
|
||||||
|
try {
|
||||||
|
s = sessionFactory().openSession();
|
||||||
|
txn = s.beginTransaction();
|
||||||
|
s.update( item );
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
fail( "expected stale write to fail" );
|
||||||
|
}
|
||||||
|
catch ( Throwable expected ) {
|
||||||
|
// expected behavior here
|
||||||
|
if ( txn != null ) {
|
||||||
|
try {
|
||||||
|
txn.rollback();
|
||||||
|
}
|
||||||
|
catch ( Throwable ignore ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( s != null && s.isOpen() ) {
|
||||||
|
try {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
catch ( Throwable ignore ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the version value in the cache...
|
||||||
|
SecondLevelCacheStatistics slcs = sessionFactory().getStatistics()
|
||||||
|
.getSecondLevelCacheStatistics( REGION_PREFIX + VersionedItem.class.getName() );
|
||||||
|
assertNotNull(slcs);
|
||||||
|
final Map entries = slcs.getEntries();
|
||||||
|
Object entry = entries.get( item.getId() );
|
||||||
|
Long cachedVersionValue;
|
||||||
|
if ( entry instanceof SoftLock ) {
|
||||||
|
//FIXME don't know what to test here
|
||||||
|
//cachedVersionValue = new Long( ( (ReadWriteCache.Lock) entry).getUnlockTimestamp() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cachedVersionValue = (Long) ( (Map) entry ).get( "_version" );
|
||||||
|
assertThat( initialVersion, equalTo( cachedVersionValue ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
s = sessionFactory().openSession();
|
||||||
|
txn = s.beginTransaction();
|
||||||
|
item = (VersionedItem) s.load( VersionedItem.class, item.getId() );
|
||||||
|
s.delete( item );
|
||||||
|
txn.commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGeneralUsage() {
|
||||||
|
EventManager mgr = new EventManager( sessionFactory() );
|
||||||
|
Statistics stats = sessionFactory().getStatistics();
|
||||||
|
|
||||||
|
// create 3 persons Steve, Orion, Tim
|
||||||
|
Person stevePerson = new Person();
|
||||||
|
stevePerson.setFirstname( "Steve" );
|
||||||
|
stevePerson.setLastname( "Harris" );
|
||||||
|
Long steveId = mgr.createAndStorePerson( stevePerson );
|
||||||
|
mgr.addEmailToPerson( steveId, "steve@tc.com" );
|
||||||
|
mgr.addEmailToPerson( steveId, "sharrif@tc.com" );
|
||||||
|
mgr.addTalismanToPerson( steveId, "rabbit foot" );
|
||||||
|
mgr.addTalismanToPerson( steveId, "john de conqueroo" );
|
||||||
|
|
||||||
|
PhoneNumber p1 = new PhoneNumber();
|
||||||
|
p1.setNumberType( "Office" );
|
||||||
|
p1.setPhone( 111111 );
|
||||||
|
mgr.addPhoneNumberToPerson( steveId, p1 );
|
||||||
|
|
||||||
|
PhoneNumber p2 = new PhoneNumber();
|
||||||
|
p2.setNumberType( "Home" );
|
||||||
|
p2.setPhone( 222222 );
|
||||||
|
mgr.addPhoneNumberToPerson( steveId, p2 );
|
||||||
|
|
||||||
|
Person orionPerson = new Person();
|
||||||
|
orionPerson.setFirstname( "Orion" );
|
||||||
|
orionPerson.setLastname( "Letizi" );
|
||||||
|
Long orionId = mgr.createAndStorePerson( orionPerson );
|
||||||
|
mgr.addEmailToPerson( orionId, "orion@tc.com" );
|
||||||
|
mgr.addTalismanToPerson( orionId, "voodoo doll" );
|
||||||
|
|
||||||
|
Long timId = mgr.createAndStorePerson( "Tim", "Teck" );
|
||||||
|
mgr.addEmailToPerson( timId, "teck@tc.com" );
|
||||||
|
mgr.addTalismanToPerson( timId, "magic decoder ring" );
|
||||||
|
|
||||||
|
Long engMeetingId = mgr.createAndStoreEvent( "Eng Meeting", stevePerson, new Date() );
|
||||||
|
mgr.addPersonToEvent( steveId, engMeetingId );
|
||||||
|
mgr.addPersonToEvent( orionId, engMeetingId );
|
||||||
|
mgr.addPersonToEvent( timId, engMeetingId );
|
||||||
|
|
||||||
|
Long docMeetingId = mgr.createAndStoreEvent( "Doc Meeting", orionPerson, new Date() );
|
||||||
|
mgr.addPersonToEvent( steveId, docMeetingId );
|
||||||
|
mgr.addPersonToEvent( orionId, docMeetingId );
|
||||||
|
|
||||||
|
for ( Event event : (List<Event>) mgr.listEvents() ) {
|
||||||
|
mgr.listEmailsOfEvent( event.getId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryStatistics queryStats = stats.getQueryStatistics( "from Event" );
|
||||||
|
assertThat( "Cache Miss Count", queryStats.getCacheMissCount(), equalTo( 1L ) );
|
||||||
|
assertThat( "Cache Hit Count", queryStats.getCacheHitCount(), equalTo( 0L ) );
|
||||||
|
assertThat( "Cache Put Count", queryStats.getCachePutCount(), equalTo( 1L ) );
|
||||||
|
}
|
||||||
|
}
|
277
hibernate-jcache/src/test/java/org/hibernate/test/cache/jcache/functional/InsertedDataTest.java
vendored
Normal file
277
hibernate-jcache/src/test/java/org/hibernate/test/cache/jcache/functional/InsertedDataTest.java
vendored
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.cache.jcache.functional;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for handling of data just inserted during a transaction being read from the database
|
||||||
|
* and placed into cache. Initially these cases went through putFromRead which causes problems because it
|
||||||
|
* loses the context of that data having just been read.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class InsertedDataTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {CacheableItem.class};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
super.addSettings( settings );
|
||||||
|
settings.put( AvailableSettings.CACHE_REGION_PREFIX, "" );
|
||||||
|
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||||
|
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||||
|
ssrb.configure( "hibernate-config/hibernate.cfg.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsert() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 1, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete CacheableItem" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertWithRollback() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
s.getTransaction().rollback();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 0, cacheMap.size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertThenUpdate() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
item.setName( "new data" );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 1, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete CacheableItem" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertThenUpdateThenRollback() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
item.setName( "new data" );
|
||||||
|
s.getTransaction().rollback();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 0, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete CacheableItem" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertWithRefresh() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
s.refresh( item );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 1, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete CacheableItem" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertWithRefreshThenRollback() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
s.refresh( item );
|
||||||
|
s.getTransaction().rollback();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 1, cacheMap.size() );
|
||||||
|
Object lock = cacheMap.values().iterator().next();
|
||||||
|
assertEquals( "org.hibernate.cache.jcache.access.AbstractReadWriteRegionAccessStrategy$Lock", lock.getClass().getName() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
item = (CacheableItem) s.get( CacheableItem.class, item.getId() );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertNull( "it should be null", item );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertWithClear() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
s.clear();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 1, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.createQuery( "delete CacheableItem" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInsertWithClearThenRollback() {
|
||||||
|
sessionFactory().getCache().evictEntityRegions();
|
||||||
|
sessionFactory().getStatistics().clear();
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
CacheableItem item = new CacheableItem( "data" );
|
||||||
|
s.save( item );
|
||||||
|
s.flush();
|
||||||
|
s.clear();
|
||||||
|
item = (CacheableItem) s.get( CacheableItem.class, item.getId() );
|
||||||
|
s.getTransaction().rollback();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Map cacheMap = sessionFactory().getStatistics().getSecondLevelCacheStatistics( "item" ).getEntries();
|
||||||
|
assertEquals( 0, cacheMap.size() );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
item = (CacheableItem) s.get( CacheableItem.class, item.getId() );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertNull( "it should be null", item );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "CacheableItem")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item")
|
||||||
|
public static class CacheableItem {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public CacheableItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheableItem(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "increment")
|
||||||
|
@GenericGenerator(name = "increment", strategy = "increment")
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,342 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.cache.jcache.functional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Version;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Zhenlei Huang
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-10649")
|
||||||
|
public class RefreshUpdatedDataTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] {
|
||||||
|
ReadWriteCacheableItem.class,
|
||||||
|
ReadWriteVersionedCacheableItem.class,
|
||||||
|
NonStrictReadWriteCacheableItem.class,
|
||||||
|
NonStrictReadWriteVersionedCacheableItem.class,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
super.addSettings( settings );
|
||||||
|
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
|
||||||
|
super.configureStandardServiceRegistryBuilder( ssrb );
|
||||||
|
ssrb.configure( "hibernate-config/hibernate.cfg.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateAndFlushThenRefresh() {
|
||||||
|
// prepare data
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
|
||||||
|
final String BEFORE = "before";
|
||||||
|
|
||||||
|
ReadWriteCacheableItem readWriteCacheableItem = new ReadWriteCacheableItem( BEFORE );
|
||||||
|
readWriteCacheableItem.getTags().add( "Hibernate" );
|
||||||
|
readWriteCacheableItem.getTags().add( "ORM" );
|
||||||
|
s.persist( readWriteCacheableItem );
|
||||||
|
|
||||||
|
ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem = new ReadWriteVersionedCacheableItem( BEFORE );
|
||||||
|
readWriteVersionedCacheableItem.getTags().add( "Hibernate" );
|
||||||
|
readWriteVersionedCacheableItem.getTags().add( "ORM" );
|
||||||
|
s.persist( readWriteVersionedCacheableItem );
|
||||||
|
|
||||||
|
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem = new NonStrictReadWriteCacheableItem( BEFORE );
|
||||||
|
nonStrictReadWriteCacheableItem.getTags().add( "Hibernate" );
|
||||||
|
nonStrictReadWriteCacheableItem.getTags().add( "ORM" );
|
||||||
|
s.persist( nonStrictReadWriteCacheableItem );
|
||||||
|
|
||||||
|
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem = new NonStrictReadWriteVersionedCacheableItem( BEFORE );
|
||||||
|
nonStrictReadWriteVersionedCacheableItem.getTags().add( "Hibernate" );
|
||||||
|
nonStrictReadWriteVersionedCacheableItem.getTags().add( "ORM" );
|
||||||
|
s.persist( nonStrictReadWriteVersionedCacheableItem );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
Session s1 = openSession();
|
||||||
|
s1.beginTransaction();
|
||||||
|
|
||||||
|
final String AFTER = "after";
|
||||||
|
|
||||||
|
ReadWriteCacheableItem readWriteCacheableItem1 = s1.get( ReadWriteCacheableItem.class, readWriteCacheableItem.getId() );
|
||||||
|
readWriteCacheableItem1.setName( AFTER );
|
||||||
|
readWriteCacheableItem1.getTags().remove("ORM");
|
||||||
|
|
||||||
|
ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem1 = s1.get( ReadWriteVersionedCacheableItem.class, readWriteVersionedCacheableItem.getId() );
|
||||||
|
readWriteVersionedCacheableItem1.setName( AFTER );
|
||||||
|
readWriteVersionedCacheableItem1.getTags().remove("ORM");
|
||||||
|
|
||||||
|
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem1 = s1.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() );
|
||||||
|
nonStrictReadWriteCacheableItem1.setName( AFTER );
|
||||||
|
nonStrictReadWriteCacheableItem1.getTags().remove("ORM");
|
||||||
|
|
||||||
|
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem1 = s1.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() );
|
||||||
|
nonStrictReadWriteVersionedCacheableItem1.setName( AFTER );
|
||||||
|
nonStrictReadWriteVersionedCacheableItem1.getTags().remove("ORM");
|
||||||
|
|
||||||
|
s1.flush();
|
||||||
|
s1.refresh( readWriteCacheableItem1 );
|
||||||
|
s1.refresh( readWriteVersionedCacheableItem1 );
|
||||||
|
s1.refresh( nonStrictReadWriteCacheableItem1 );
|
||||||
|
s1.refresh( nonStrictReadWriteVersionedCacheableItem1 );
|
||||||
|
|
||||||
|
assertEquals( AFTER, readWriteCacheableItem1.getName() );
|
||||||
|
assertEquals( 1, readWriteCacheableItem1.getTags().size() );
|
||||||
|
assertEquals( AFTER, readWriteVersionedCacheableItem1.getName() );
|
||||||
|
assertEquals( 1, readWriteVersionedCacheableItem1.getTags().size() );
|
||||||
|
assertEquals( AFTER, nonStrictReadWriteCacheableItem1.getName() );
|
||||||
|
assertEquals( 1, nonStrictReadWriteCacheableItem1.getTags().size() );
|
||||||
|
assertEquals( AFTER, nonStrictReadWriteVersionedCacheableItem1.getName() );
|
||||||
|
assertEquals( 1, nonStrictReadWriteVersionedCacheableItem1.getTags().size() );
|
||||||
|
|
||||||
|
// open another session
|
||||||
|
Session s2 = sessionFactory().openSession();
|
||||||
|
try {
|
||||||
|
s2.beginTransaction();
|
||||||
|
ReadWriteCacheableItem readWriteCacheableItem2 = s2.get( ReadWriteCacheableItem.class, readWriteCacheableItem.getId() );
|
||||||
|
ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem2 = s2.get( ReadWriteVersionedCacheableItem.class, readWriteVersionedCacheableItem.getId() );
|
||||||
|
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem2 = s2.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() );
|
||||||
|
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem2 = s2.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() );
|
||||||
|
|
||||||
|
assertEquals( BEFORE, readWriteCacheableItem2.getName() );
|
||||||
|
assertEquals( 2, readWriteCacheableItem2.getTags().size() );
|
||||||
|
assertEquals( BEFORE, readWriteVersionedCacheableItem2.getName() );
|
||||||
|
assertEquals( 2, readWriteVersionedCacheableItem2.getTags().size() );
|
||||||
|
|
||||||
|
//READ_UNCOMMITTED because there is no locking to prevent collections from being cached in the first Session
|
||||||
|
|
||||||
|
assertEquals( BEFORE, nonStrictReadWriteCacheableItem2.getName() );
|
||||||
|
assertEquals( 1, nonStrictReadWriteCacheableItem2.getTags().size());
|
||||||
|
assertEquals( BEFORE, nonStrictReadWriteVersionedCacheableItem2.getName() );
|
||||||
|
assertEquals( 1, nonStrictReadWriteVersionedCacheableItem2.getTags().size() );
|
||||||
|
|
||||||
|
s2.getTransaction().commit();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ( s2.getTransaction().getStatus().canRollback() ) {
|
||||||
|
s2.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
s2.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
s1.getTransaction().rollback();
|
||||||
|
s1.close();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.delete( readWriteCacheableItem );
|
||||||
|
s.delete( readWriteVersionedCacheableItem );
|
||||||
|
s.delete( nonStrictReadWriteCacheableItem );
|
||||||
|
s.delete( nonStrictReadWriteVersionedCacheableItem );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "ReadWriteCacheableItem")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item")
|
||||||
|
public static class ReadWriteCacheableItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||||
|
@ElementCollection
|
||||||
|
private List<String> tags = new ArrayList<>();
|
||||||
|
|
||||||
|
public ReadWriteCacheableItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadWriteCacheableItem(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "ReadWriteVersionedCacheableItem")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item")
|
||||||
|
public static class ReadWriteVersionedCacheableItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||||
|
@ElementCollection
|
||||||
|
private List<String> tags = new ArrayList<>();
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
public ReadWriteVersionedCacheableItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadWriteVersionedCacheableItem(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "NonStrictReadWriteCacheableItem")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item")
|
||||||
|
public static class NonStrictReadWriteCacheableItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||||
|
@ElementCollection
|
||||||
|
private List<String> tags = new ArrayList<>();
|
||||||
|
|
||||||
|
public NonStrictReadWriteCacheableItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NonStrictReadWriteCacheableItem(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "NonStrictReadWriteVersionedCacheableItem")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item")
|
||||||
|
public static class NonStrictReadWriteVersionedCacheableItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||||
|
@ElementCollection
|
||||||
|
private List<String> tags = new ArrayList<>();
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private int version;
|
||||||
|
|
||||||
|
public NonStrictReadWriteVersionedCacheableItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NonStrictReadWriteVersionedCacheableItem(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
public class Account {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private Person person;
|
||||||
|
|
||||||
|
public Account() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getPerson() {
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPerson(Person person) {
|
||||||
|
this.person = person;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Event {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private Date date;
|
||||||
|
private Set participants = new HashSet();
|
||||||
|
private Person organizer;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganizer(Person organizer) {
|
||||||
|
this.organizer = organizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person getOrganizer() {
|
||||||
|
return organizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set getParticipants() {
|
||||||
|
return participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParticipants(Set participants) {
|
||||||
|
this.participants = participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addParticipant(Person person) {
|
||||||
|
participants.add(person);
|
||||||
|
person.getEvents().add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeParticipant(Person person) {
|
||||||
|
participants.remove(person);
|
||||||
|
person.getEvents().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getTitle() + ": " + getDate();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
|
import org.hibernate.Query;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
|
||||||
|
public class EventManager {
|
||||||
|
|
||||||
|
private final SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
public EventManager(SessionFactory sessionFactory) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List listEmailsOfEvent(Long eventId) {
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
List emailList = new ArrayList();
|
||||||
|
Event event = (Event)session.load(Event.class, eventId);
|
||||||
|
for (Iterator it = event.getParticipants().iterator(); it.hasNext(); ) {
|
||||||
|
Person person = (Person)it.next();
|
||||||
|
emailList.addAll(person.getEmailAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return emailList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long createAndStoreEvent(String title, Person organizer, Date theDate) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Event theEvent = new Event();
|
||||||
|
theEvent.setTitle(title);
|
||||||
|
theEvent.setDate(theDate);
|
||||||
|
theEvent.setOrganizer(organizer);
|
||||||
|
|
||||||
|
Long eventId = (Long)session.save(theEvent);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long createAndStorePerson(String firstName, String lastName) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person person = new Person();
|
||||||
|
person.setFirstname(firstName);
|
||||||
|
person.setLastname(lastName);
|
||||||
|
|
||||||
|
Long personId = (Long)session.save(person);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long createAndStorePerson(Person person) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Long personId = (Long)session.save(person);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List listEvents() {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
List result = session.createQuery("from Event").setCacheable(true).list();
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call setEntity() on a cacheable query - see FORGE-265
|
||||||
|
*/
|
||||||
|
public List listEventsOfOrganizer(Person organizer) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Query query = session.createQuery("from Event ev where ev.organizer = :organizer");
|
||||||
|
|
||||||
|
query.setCacheable(true);
|
||||||
|
query.setEntity("organizer", organizer);
|
||||||
|
List result = query.list();
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use a Criteria query - see FORGE-247
|
||||||
|
*/
|
||||||
|
public List listEventsWithCriteria() {
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
List result = session.createCriteria(Event.class)
|
||||||
|
.setCacheable(true)
|
||||||
|
.list();
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPersonToEvent(Long personId, Long eventId) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person aPerson = (Person)session.load(Person.class, personId);
|
||||||
|
Event anEvent = (Event)session.load(Event.class, eventId);
|
||||||
|
|
||||||
|
aPerson.getEvents().add(anEvent);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long addPersonToAccount(Long personId, Account account) {
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person aPerson = (Person)session.load(Person.class, personId);
|
||||||
|
account.setPerson(aPerson);
|
||||||
|
|
||||||
|
Long accountId = (Long)session.save(account);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount(Long accountId) {
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Account account = (Account)session.load(Account.class, accountId);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEmailToPerson(Long personId, String emailAddress) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person aPerson = (Person)session.load(Person.class, personId);
|
||||||
|
|
||||||
|
// The getEmailAddresses() might trigger a lazy load of the collection
|
||||||
|
aPerson.getEmailAddresses().add(emailAddress);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPhoneNumberToPerson(Long personId, PhoneNumber pN) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person aPerson = (Person)session.load(Person.class, personId);
|
||||||
|
pN.setPersonId(personId.longValue());
|
||||||
|
aPerson.getPhoneNumbers().add(pN);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTalismanToPerson(Long personId, String talisman) {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
Person aPerson = (Person)session.load(Person.class, personId);
|
||||||
|
aPerson.addTalisman(talisman);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long createHolidayCalendar() {
|
||||||
|
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
// delete all existing calendars
|
||||||
|
List calendars = session.createQuery("from HolidayCalendar").setCacheable(true).list();
|
||||||
|
for (ListIterator li = calendars.listIterator(); li.hasNext(); ) {
|
||||||
|
session.delete(li.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
HolidayCalendar calendar = new HolidayCalendar();
|
||||||
|
calendar.init();
|
||||||
|
|
||||||
|
Long calendarId = (Long)session.save(calendar);
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
return calendarId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HolidayCalendar getHolidayCalendar() {
|
||||||
|
Session session = sessionFactory.getCurrentSession();
|
||||||
|
|
||||||
|
session.beginTransaction();
|
||||||
|
|
||||||
|
List calendars = session.createQuery("from HolidayCalendar").setCacheable(true).list();
|
||||||
|
|
||||||
|
session.getTransaction().commit();
|
||||||
|
|
||||||
|
return calendars.isEmpty() ? null : (HolidayCalendar)calendars.get(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HolidayCalendar {
|
||||||
|
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
// Date -> String
|
||||||
|
private Map holidays = new HashMap();
|
||||||
|
|
||||||
|
public HolidayCalendar init() {
|
||||||
|
DateFormat df = new SimpleDateFormat("yyyy.MM.dd");
|
||||||
|
try {
|
||||||
|
holidays.clear();
|
||||||
|
holidays.put(df.parse("2009.01.01"), "New Year's Day");
|
||||||
|
holidays.put(df.parse("2009.02.14"), "Valentine's Day");
|
||||||
|
holidays.put(df.parse("2009.11.11"), "Armistice Day");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map getHolidays() {
|
||||||
|
return holidays;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setHolidays(Map holidays) {
|
||||||
|
this.holidays = holidays;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHoliday(Date d, String name) {
|
||||||
|
holidays.put(d, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHoliday(Date d) {
|
||||||
|
return (String)holidays.get(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHoliday(Date d) {
|
||||||
|
return holidays.containsKey(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
public class Item {
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private int age;
|
||||||
|
private String firstname;
|
||||||
|
private String lastname;
|
||||||
|
private List events = new ArrayList(); // list semantics, e.g., indexed
|
||||||
|
private Set emailAddresses = new HashSet();
|
||||||
|
private Set phoneNumbers = new HashSet();
|
||||||
|
private List talismans = new ArrayList(); // a Bag of good-luck charms.
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getEvents() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setEvents(List events) {
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addToEvent(Event event) {
|
||||||
|
this.getEvents().add(event);
|
||||||
|
event.getParticipants().add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeFromEvent(Event event) {
|
||||||
|
this.getEvents().remove(event);
|
||||||
|
event.getParticipants().remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstname() {
|
||||||
|
return firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstname(String firstname) {
|
||||||
|
this.firstname = firstname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastname() {
|
||||||
|
return lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastname(String lastname) {
|
||||||
|
this.lastname = lastname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set getEmailAddresses() {
|
||||||
|
return emailAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailAddresses(Set emailAddresses) {
|
||||||
|
this.emailAddresses = emailAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set getPhoneNumbers() {
|
||||||
|
return phoneNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhoneNumbers(Set phoneNumbers) {
|
||||||
|
this.phoneNumbers = phoneNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTalisman(String name) {
|
||||||
|
talismans.add(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getTalismans() {
|
||||||
|
return talismans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTalismans(List talismans) {
|
||||||
|
this.talismans = talismans;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getFirstname() + " " + getLastname();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhoneNumber
|
||||||
|
*/
|
||||||
|
public class PhoneNumber implements Serializable {
|
||||||
|
private long personId = 0;
|
||||||
|
private String numberType = "home";
|
||||||
|
private long phone = 0;
|
||||||
|
|
||||||
|
public long getPersonId() {
|
||||||
|
return personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonId(long personId) {
|
||||||
|
this.personId = personId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumberType() {
|
||||||
|
return numberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNumberType(String numberType) {
|
||||||
|
this.numberType = numberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPhone(long phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result
|
||||||
|
+ ((numberType == null) ? 0 : numberType.hashCode());
|
||||||
|
result = prime * result + (int)(personId ^ (personId >>> 32));
|
||||||
|
result = prime * result + (int)(phone ^ (phone >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
final PhoneNumber other = (PhoneNumber)obj;
|
||||||
|
if (numberType == null) {
|
||||||
|
if (other.numberType != null)
|
||||||
|
return false;
|
||||||
|
} else if (!numberType.equals(other.numberType))
|
||||||
|
return false;
|
||||||
|
if (personId != other.personId)
|
||||||
|
return false;
|
||||||
|
if (phone != other.phone)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return numberType + ":" + phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
public class UuidItem {
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.test.domain;
|
||||||
|
|
||||||
|
public class VersionedItem extends Item {
|
||||||
|
private Long version;
|
||||||
|
|
||||||
|
public Long getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(Long version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping>
|
||||||
|
|
||||||
|
<class name="org.hibernate.test.domain.Account" table="ACCOUNT" lazy="false">
|
||||||
|
<id name="id" column="ACCOUNT_ID">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
|
||||||
|
<many-to-one name="person" class="org.hibernate.test.domain.Person" cascade="save-update,lock"
|
||||||
|
column="person_id"
|
||||||
|
unique="true"
|
||||||
|
not-null="true"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping>
|
||||||
|
|
||||||
|
<class name="org.hibernate.test.domain.Event" table="EVENTS">
|
||||||
|
<cache usage="read-write"/>
|
||||||
|
<id name="id" column="EVENT_ID">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
<property name="date" type="timestamp" column="EVENT_DATE"/>
|
||||||
|
<property name="title"/>
|
||||||
|
<many-to-one name="organizer" column="EVENT_ORGANIZER" class="org.hibernate.test.domain.Person"/>
|
||||||
|
|
||||||
|
<set name="participants" table="PERSON_EVENT" lazy="false"
|
||||||
|
inverse="true" cascade="lock">
|
||||||
|
<cache usage="read-write"/>
|
||||||
|
<key column="EVENT_ID"/>
|
||||||
|
<many-to-many column="PERSON_ID"
|
||||||
|
class="org.hibernate.test.domain.Person"/>
|
||||||
|
</set>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping>
|
||||||
|
|
||||||
|
<class name="org.hibernate.test.domain.HolidayCalendar" table="CALENDAR" lazy="false">
|
||||||
|
<id name="id" column="CALENDAR_ID">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
|
||||||
|
<map name="holidays" table="CALENDAR_HOLIDAYS" lazy="false">
|
||||||
|
<key column="CALENDAR_ID"/>
|
||||||
|
<map-key column="hol_date" type="date"/>
|
||||||
|
<element column="hol_name" type="string"/>
|
||||||
|
</map>
|
||||||
|
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping package="org.hibernate.test.domain">
|
||||||
|
|
||||||
|
|
||||||
|
<class name="Item" table="Items">
|
||||||
|
<cache usage="read-write"/>
|
||||||
|
<id name="id">
|
||||||
|
<generator class="increment"/>
|
||||||
|
</id>
|
||||||
|
<property name="name" not-null="true"/>
|
||||||
|
<property name="description" not-null="true"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
<class name="VersionedItem" table="VersionedItems">
|
||||||
|
<cache usage="read-write"/>
|
||||||
|
<id name="id">
|
||||||
|
<generator class="increment"/>
|
||||||
|
</id>
|
||||||
|
<version name="version" type="long"/>
|
||||||
|
<property name="name" not-null="true"/>
|
||||||
|
<property name="description" not-null="true"/>
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping>
|
||||||
|
|
||||||
|
<class name="org.hibernate.test.domain.Person" table="PERSON" lazy="true">
|
||||||
|
<id name="id" column="PERSON_ID">
|
||||||
|
<generator class="native"/>
|
||||||
|
</id>
|
||||||
|
<property name="age"/>
|
||||||
|
<property name="firstname"/>
|
||||||
|
<property name="lastname"/>
|
||||||
|
|
||||||
|
<list name="events" table="PERSON_EVENT" lazy="true">
|
||||||
|
<key column="PERSON_ID"/>
|
||||||
|
<list-index column="EVENT_ORDER"/>
|
||||||
|
<many-to-many column="EVENT_ID" class="org.hibernate.test.domain.Event"/>
|
||||||
|
</list>
|
||||||
|
|
||||||
|
<bag name="talismans" table="PERSON_TALISMAN" lazy="true">
|
||||||
|
<key column="PERSON_ID"/>
|
||||||
|
<element type="string" column="TALISMAN_NAME"/>
|
||||||
|
</bag>
|
||||||
|
|
||||||
|
<set name="emailAddresses" table="PERSON_EMAIL_ADDR" lazy="true">
|
||||||
|
<key column="PERSON_ID"/>
|
||||||
|
<element type="string" column="EMAIL_ADDR"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
<set name="phoneNumbers" cascade="all" lazy="true">
|
||||||
|
<key column="PERSON_ID"/>
|
||||||
|
<one-to-many class="org.hibernate.test.domain.PhoneNumber"/>
|
||||||
|
</set>
|
||||||
|
|
||||||
|
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-mapping PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||||
|
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-mapping>
|
||||||
|
|
||||||
|
<class name="org.hibernate.test.domain.PhoneNumber" table="PHONE_NUMBERS">
|
||||||
|
<composite-id>
|
||||||
|
<key-property column="PERSON_ID" name="personId" type="java.lang.Long"/>
|
||||||
|
<key-property column="NUMBER_TYPE" name="numberType" type="java.lang.String"/>
|
||||||
|
</composite-id>
|
||||||
|
|
||||||
|
<property name="phone" type="java.lang.Long">
|
||||||
|
<column name="PHONE" precision="22" scale="0"/>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
</class>
|
||||||
|
|
||||||
|
</hibernate-mapping>
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<!--
|
||||||
|
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
~
|
||||||
|
~ License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
~ See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
-->
|
||||||
|
<!DOCTYPE hibernate-configuration PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||||
|
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||||
|
|
||||||
|
<hibernate-configuration>
|
||||||
|
|
||||||
|
<session-factory>
|
||||||
|
|
||||||
|
<!-- Database connection settings -->
|
||||||
|
<!-- <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
|
||||||
|
<property name="connection.url">jdbc:hsqldb:hsql://localhost/TestDB</property> -->
|
||||||
|
|
||||||
|
<property name="connection.driver_class">org.h2.Driver</property>
|
||||||
|
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
|
||||||
|
<property name="connection.username">sa</property>
|
||||||
|
<property name="connection.password"></property>
|
||||||
|
|
||||||
|
<!-- JDBC connection pool (use the built-in) -->
|
||||||
|
<property name="connection.pool_size">1</property>
|
||||||
|
|
||||||
|
<!-- SQL dialect -->
|
||||||
|
<property name="dialect">
|
||||||
|
org.hibernate.dialect.H2Dialect
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<!-- Enable Hibernate's automatic session context management -->
|
||||||
|
<property name="current_session_context_class">thread</property>
|
||||||
|
|
||||||
|
<property name="cache.use_query_cache">true</property>
|
||||||
|
<property name="cache.use_second_level_cache">true</property>
|
||||||
|
<property name="cache.use_structured_entries">true</property>
|
||||||
|
<property name="cache.region.factory_class">org.hibernate.cache.jcache.JCacheRegionFactory</property>
|
||||||
|
<property name="net.sf.ehcache.configurationResourceName">/hibernate-config/ehcache.xml</property>
|
||||||
|
<!-- Echo all executed SQL to stdout -->
|
||||||
|
<property name="show_sql">true</property>
|
||||||
|
|
||||||
|
<mapping resource="hibernate-config/domain/Event.hbm.xml"/>
|
||||||
|
<mapping resource="hibernate-config/domain/Person.hbm.xml"/>
|
||||||
|
<mapping resource="hibernate-config/domain/PhoneNumber.hbm.xml"/>
|
||||||
|
<mapping resource="hibernate-config/domain/Account.hbm.xml"/>
|
||||||
|
<mapping resource="hibernate-config/domain/HolidayCalendar.hbm.xml"/>
|
||||||
|
|
||||||
|
<mapping resource="hibernate-config/domain/Item.hbm.xml"/>
|
||||||
|
|
||||||
|
</session-factory>
|
||||||
|
|
||||||
|
</hibernate-configuration>
|
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
#
|
||||||
|
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
#
|
||||||
|
hibernate.dialect @db.dialect@
|
||||||
|
hibernate.connection.driver_class @jdbc.driver@
|
||||||
|
hibernate.connection.url @jdbc.url@
|
||||||
|
hibernate.connection.username @jdbc.user@
|
||||||
|
hibernate.connection.password @jdbc.pass@
|
||||||
|
|
||||||
|
hibernate.connection.pool_size 5
|
||||||
|
|
||||||
|
hibernate.cache.region_prefix hibernate.test
|
||||||
|
|
||||||
|
hibernate.service.allow_crawling=false
|
|
@ -0,0 +1,17 @@
|
||||||
|
#
|
||||||
|
# Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
#
|
||||||
|
# License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
# See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
#
|
||||||
|
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||||
|
log4j.appender.stdout.Target=System.out
|
||||||
|
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||||
|
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
|
||||||
|
|
||||||
|
log4j.rootLogger=info, stdout
|
||||||
|
|
||||||
|
log4j.logger.org.hibernate.test=info
|
||||||
|
|
||||||
|
# SQL Logging - HHH-6833
|
||||||
|
log4j.logger.org.hibernate.SQL=debug
|
Loading…
Reference in New Issue