Merge branch 'master' of github.com:hibernate/hibernate-core

This commit is contained in:
Gail Badner 2011-01-17 12:26:43 -08:00
commit a6d19f257b
15 changed files with 317 additions and 49 deletions

View File

@ -1141,15 +1141,20 @@ public class StatefulPersistenceContext implements PersistenceContext {
final CollectionPersister collectionPersister = session.getFactory().getCollectionPersister( collectionRole );
// try cache lookup first
Object parent = parentsByChild.get(childEntity);
if (parent != null) {
if (isFoundInParent(propertyName, childEntity, persister, collectionPersister, parent)) {
return getEntry(parent).getId();
}
else {
parentsByChild.remove(childEntity); // remove wrong entry
}
Object parent = parentsByChild.get( childEntity );
if ( parent != null ) {
final EntityEntry entityEntry = ( EntityEntry ) entityEntries.get( parent );
//there maybe more than one parent, filter by type
if ( persister.isSubclassEntityName(entityEntry.getEntityName() )
&& isFoundInParent( propertyName, childEntity, persister, collectionPersister, parent ) ) {
return getEntry( parent ).getId();
}
else {
parentsByChild.remove( childEntity ); // remove wrong entry
}
}
//not found in case, proceed
// iterate all the entities currently associated with the persistence context.
Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
@ -1257,21 +1262,28 @@ public class StatefulPersistenceContext implements PersistenceContext {
// try cache lookup first
Object parent = parentsByChild.get(childEntity);
if (parent != null) {
Object index = getIndexInParent(property, childEntity, persister, cp, parent);
if (index==null && mergeMap!=null) {
Object unmergedInstance = mergeMap.get(parent);
Object unmergedChild = mergeMap.get(childEntity);
if ( unmergedInstance!=null && unmergedChild!=null ) {
index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
final EntityEntry entityEntry = (EntityEntry) entityEntries.get(parent);
//there maybe more than one parent, filter by type
if ( persister.isSubclassEntityName( entityEntry.getEntityName() ) ) {
Object index = getIndexInParent(property, childEntity, persister, cp, parent);
if (index==null && mergeMap!=null) {
Object unmergedInstance = mergeMap.get(parent);
Object unmergedChild = mergeMap.get(childEntity);
if ( unmergedInstance!=null && unmergedChild!=null ) {
index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
}
}
if (index!=null) {
return index;
}
}
if (index!=null) {
return index;
else {
parentsByChild.remove(childEntity); // remove wrong entry
}
parentsByChild.remove(childEntity); // remove wrong entry
}
//Not found in cache, proceed
Iterator entities = IdentityMap.entries(entityEntries).iterator();
while ( entities.hasNext() ) {
Map.Entry me = (Map.Entry) entities.next();

View File

@ -0,0 +1,35 @@
package org.hibernate.test.annotations.engine.collection;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
/**
* @author Emmanuel Bernard
*/
@Entity
@Table(name = "co_father")
public class Father {
@Id
@GeneratedValue
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Integer id;
@OneToMany
@OrderColumn(name = "son_arriv")
@JoinColumn(name = "father_id", nullable = false)
@Cascade({ CascadeType.SAVE_UPDATE })
public List<Son> getOrderedSons() { return orderedSons; }
public void setOrderedSons(List<Son> orderedSons) { this.orderedSons = orderedSons; }
private List<Son> orderedSons = new ArrayList<Son>( );
}

View File

@ -0,0 +1,31 @@
package org.hibernate.test.annotations.engine.collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
/**
* @author Emmanuel Bernard
*/
@Entity
@Table(name = "co_mother")
public class Mother {
@Id
@GeneratedValue
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Integer id;
@OneToMany(mappedBy = "mother")
@Cascade({ CascadeType.SAVE_UPDATE })
public Set<Son> getSons() { return sons; }
public void setSons(Set<Son> sons) { this.sons = sons; }
private Set<Son> sons = new HashSet<Son>();
}

View File

@ -0,0 +1,31 @@
package org.hibernate.test.annotations.engine.collection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
* @author Emmanuel Bernard
*/
@Entity
@Table(name="co_son")
public class Son {
@Id
@GeneratedValue
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
private Integer id;
@ManyToOne(optional = false) @JoinColumn(name = "father_id", insertable = false, updatable = false, nullable = false)
public Father getFather() { return father; }
public void setFather(Father father) { this.father = father; }
private Father father;
@ManyToOne
public Mother getMother() { return mother; }
public void setMother(Mother mother) { this.mother = mother; }
private Mother mother;
}

View File

@ -0,0 +1,51 @@
package org.hibernate.test.annotations.engine.collection;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.annotations.TestCase;
/**
* @author Emmanuel Bernard
*/
public class UnidirCollectionWithMultipleOwnerTest extends TestCase {
public void testUnidirCollectionWithMultipleOwner() throws Exception {
Session s = openSession();
Transaction tx;
tx = s.beginTransaction();
Father father = new Father();
Mother mother = new Mother();
s.save( father );
//s.save( mother );
Son son = new Son();
father.getOrderedSons().add( son );
son.setFather( father );
mother.getSons().add( son );
son.setMother( mother );
s.save( mother );
s.save( father );
tx.commit();
s.clear();
tx = s.beginTransaction();
son = (Son) s.get( Son.class, son.getId() );
s.delete( son );
s.flush();
father = (Father) s.get( Father.class, father.getId() );
mother = (Mother) s.get( Mother.class, mother.getId() );
s.delete( father );
s.delete( mother );
tx.commit();
s.close();
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Father.class,
Mother.class,
Son.class
};
}
}

View File

@ -280,11 +280,11 @@ public class AuditReaderImpl implements AuditReaderImplementor {
entity = ((HibernateProxy)entity).getHibernateLazyInitializer().getImplementation();
}
if(firstLevelCache.containsEntityName(primaryKey, revision, entity)) {
// it´s on envers FLC!
// it's on envers FLC!
return firstLevelCache.getFromEntityNameCache(primaryKey, revision, entity);
} else {
throw new HibernateException(
"Envers can´t resolve entityName for historic entity. The id, revision and entity is not on envers first level cache.");
"Envers can't resolve entityName for historic entity. The id, revision and entity is not on envers first level cache.");
}
}
}

View File

@ -84,8 +84,7 @@ public class TimestampsRegionImpl extends BaseGeneralDataRegion implements Times
try {
// We ensure ASYNC semantics (JBCACHE-1175) and make sure previous
// value is not loaded from cache store cos it's not needed.
cacheAdapter.withFlags(FlagAdapter.FORCE_ASYNCHRONOUS,
FlagAdapter.SKIP_CACHE_LOAD).put(key, value);
cacheAdapter.withFlags(FlagAdapter.FORCE_ASYNCHRONOUS).put(key, value);
} catch (Exception e) {
throw new CacheException(e);
} finally {

View File

@ -101,27 +101,25 @@ public interface CacheAdapter {
Object getAllowingTimeout(Object key) throws CacheException;
/**
* Performs a <code>put(Object, Object)</code> on the cache, wrapping any exception in a {@link CacheException}.
* Performs a <code>put(Object, Object)</code> on the cache,
* wrapping any exception in a {@link CacheException}.
*
* @param key key whose value will be modified
* @param value data to store in the cache entry
* @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
* if there was no mapping for <tt>key</tt>.
* @throws CacheException
*/
Object put(Object key, Object value) throws CacheException;
void put(Object key, Object value) throws CacheException;
/**
* Performs a <code>put(Object, Object)</code> on the cache ignoring any {@link TimeoutException}
* and wrapping any exception in a {@link CacheException}.
* Performs a <code>put(Object, Object)</code> on the cache ignoring
* any {@link TimeoutException} and wrapping any exception in a
* {@link CacheException}.
*
* @param key key whose value will be modified
* @param value data to store in the cache entry
* @return the previous value associated with <tt>key</tt>, or <tt>null</tt>
* if there was no mapping for <tt>key</tt>.
* @throws CacheException
*/
Object putAllowingTimeout(Object key, Object value) throws CacheException;
void putAllowingTimeout(Object key, Object value) throws CacheException;
/**
* See {@link Cache#putForExternalRead(Object, Object)} for detailed documentation.
@ -133,14 +131,13 @@ public interface CacheAdapter {
void putForExternalRead(Object key, Object value) throws CacheException;
/**
* Performs a <code>remove(Object)</code>, wrapping any exception in a {@link CacheException}.
* Performs a <code>remove(Object)</code>, wrapping any exception in
* a {@link CacheException}.
*
* @param key key to be removed
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* @throws CacheException
*/
Object remove(Object key) throws CacheException;
void remove(Object key) throws CacheException;
/**
* Evict the given key from memory.

View File

@ -94,20 +94,21 @@ public class CacheAdapterImpl implements CacheAdapter {
}
}
public Object put(Object key, Object value) throws CacheException {
public void put(Object key, Object value) throws CacheException {
try {
return cache.put(key, value);
// No previous value interest, so apply flags that avoid remote lookups.
getSkipRemoteGetLoadCache().put(key, value);
} catch (Exception e) {
throw new CacheException(e);
}
}
public Object putAllowingTimeout(Object key, Object value) throws CacheException {
public void putAllowingTimeout(Object key, Object value) throws CacheException {
try {
return getFailSilentCache().put(key, value);
// No previous value interest, so apply flags that avoid remote lookups.
getFailSilentCacheSkipRemotes().put(key, value);
} catch (TimeoutException allowed) {
// ignore it
return null;
} catch (Exception e) {
throw new CacheException(e);
}
@ -115,15 +116,17 @@ public class CacheAdapterImpl implements CacheAdapter {
public void putForExternalRead(Object key, Object value) throws CacheException {
try {
cache.putForExternalRead(key, value);
// No previous value interest, so apply flags that avoid remote lookups.
getFailSilentCacheSkipRemotes().putForExternalRead(key, value);
} catch (Exception e) {
throw new CacheException(e);
}
}
public Object remove(Object key) throws CacheException {
public void remove(Object key) throws CacheException {
try {
return cache.remove(key);
// No previous value interest, so apply flags that avoid remote lookups.
getSkipRemoteGetLoadCache().remove(key);
} catch (Exception e) {
throw new CacheException(e);
}
@ -214,4 +217,15 @@ public class CacheAdapterImpl implements CacheAdapter {
private Cache getFailSilentCache() {
return cache.getAdvancedCache().withFlags(Flag.FAIL_SILENTLY);
}
private Cache getSkipRemoteGetLoadCache() {
return cache.getAdvancedCache().withFlags(
Flag.SKIP_CACHE_LOAD, Flag.SKIP_REMOTE_LOOKUP);
}
private Cache getFailSilentCacheSkipRemotes() {
return cache.getAdvancedCache().withFlags(
Flag.FAIL_SILENTLY, Flag.SKIP_CACHE_LOAD, Flag.SKIP_REMOTE_LOOKUP);
}
}

View File

@ -48,14 +48,14 @@ public class CacheHelper {
private CacheHelper() {
}
public static void initInternalEvict(CacheAdapter cacheAdapter, AddressAdapter member) {
public static void initInternalEvict(CacheAdapter cache, AddressAdapter member) {
EvictAll eKey = new EvictAll(member == null ? NoAddress.INSTANCE : member);
cacheAdapter.withFlags(FlagAdapter.CACHE_MODE_LOCAL, FlagAdapter.SKIP_CACHE_LOAD).put(eKey, Internal.INIT);
cache.withFlags(FlagAdapter.CACHE_MODE_LOCAL).put(eKey, Internal.INIT);
}
public static void sendEvictAllNotification(CacheAdapter cacheAdapter, AddressAdapter member) {
public static void sendEvictAllNotification(CacheAdapter cache, AddressAdapter member) {
EvictAll eKey = new EvictAll(member == null ? NoAddress.INSTANCE : member);
cacheAdapter.withFlags(FlagAdapter.SKIP_CACHE_LOAD).put(eKey, Internal.EVICT);
cache.put(eKey, Internal.EVICT);
}
public static boolean isEvictAllNotification(Object key) {

View File

@ -4,4 +4,5 @@ dependencies {
compile( project( ':hibernate-core' ) )
compile( [group: 'proxool', name: 'proxool', version: '0.8.3'] )
testCompile( project(':hibernate-core').sourceSets.test.classes )
testRuntime( libraries.h2 )
}

View File

@ -202,7 +202,12 @@ public class ProxoolConnectionProvider implements ConnectionProvider {
// We have created the pool ourselves, so shut it down
try {
ProxoolFacade.shutdown(0);
if ( ProxoolFacade.getAliases().length == 1 ) {
ProxoolFacade.shutdown( 0 );
}
else {
ProxoolFacade.removeConnectionPool(proxoolAlias.substring(PROXOOL_JDBC_STEM.length()));
}
}
catch (Exception e) {
// If you're closing down the ConnectionProvider chances are an

View File

@ -0,0 +1,78 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.connections.internal;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.hibernate.cfg.Environment;
import org.logicalcobwebs.proxool.ProxoolFacade;
import junit.framework.TestCase;
/**
* Test to verify connection pools are closed, and that only the managed one is closed.
* @author Sanne Grinovero
*/
public class ProxoolConnectionProviderTest extends TestCase {
public void testPoolsClosed() {
assertDefinedPools(); // zero-length-vararg used as parameter
ProxoolConnectionProvider providerOne = new ProxoolConnectionProvider();
providerOne.configure( getPoolConfigurarion( "pool-one" ) );
assertDefinedPools( "pool-one" );
ProxoolConnectionProvider providerTwo = new ProxoolConnectionProvider();
providerTwo.configure( getPoolConfigurarion( "pool-two" ) );
assertDefinedPools( "pool-one", "pool-two" );
providerOne.close();
assertDefinedPools( "pool-two" );
providerTwo.close();
assertDefinedPools();
}
private void assertDefinedPools(String... expectedPoolNames) {
List<String> aliases = Arrays.asList( ProxoolFacade.getAliases() );
assertEquals( expectedPoolNames.length, aliases.size() );
for (String poolName : expectedPoolNames) {
assertTrue( "pool named " + poolName + " missing", aliases.contains( poolName ) );
}
}
/**
* @param pool name
* @return his configuration - see src/tests/resources for matches
*/
private Properties getPoolConfigurarion(String poolName) {
Properties cfg = new Properties();
cfg.setProperty( Environment.PROXOOL_POOL_ALIAS, poolName );
cfg.setProperty( Environment.PROXOOL_PROPERTIES, poolName + ".properties" );
return cfg;
}
}

View File

@ -0,0 +1,7 @@
jdbc-0.proxool.alias=pool-one
jdbc-0.proxool.driver-url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
jdbc-0.proxool.driver-class=org.h2.Driver
jdbc-0.user=sa
jdbc-0.password=
jdbc-0.proxool.maximum-connection-count=2
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE

View File

@ -0,0 +1,7 @@
jdbc-0.proxool.alias=pool-two
jdbc-0.proxool.driver-url=jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE
jdbc-0.proxool.driver-class=org.h2.Driver
jdbc-0.user=sa
jdbc-0.password=
jdbc-0.proxool.maximum-connection-count=2
jdbc-0.proxool.house-keeping-test-sql=select CURRENT_DATE