HHH-12771 - Caused by: java.lang.UnsupportedOperationException: Cache provider [org.hibernate.cache.ehcache.internal.EhcacheRegionFactory@3271ec2a] does not support `transactional` access
This commit is contained in:
parent
bb71c63853
commit
4b51867c44
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.cache.spi;
|
package org.hibernate.cache.spi;
|
||||||
|
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||||
|
|
||||||
import org.jboss.logging.BasicLogger;
|
import org.jboss.logging.BasicLogger;
|
||||||
|
@ -90,4 +91,12 @@ public interface SecondLevelCacheLogger extends BasicLogger {
|
||||||
)
|
)
|
||||||
void usingLegacyCacheName(String currentName, String legacyName);
|
void usingLegacyCacheName(String currentName, String legacyName);
|
||||||
|
|
||||||
|
@LogMessage(level = WARN)
|
||||||
|
@Message(
|
||||||
|
value = "Cache [%1$s] uses the [%2$s] access type, but [%3$s] does not support it natively." +
|
||||||
|
" Make sure your cache implementation supports JTA transactions.",
|
||||||
|
id = NAMESPACE + 8
|
||||||
|
)
|
||||||
|
void nonStandardSupportForAccessType(String key, String accessType, String regionName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.cache;
|
package org.hibernate.cache.spi.support;
|
||||||
|
|
||||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.cache;
|
package org.hibernate.cache.spi.support;
|
||||||
|
|
||||||
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||||
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||||
|
@ -15,7 +15,6 @@ import org.hibernate.cache.spi.CacheKeysFactory;
|
||||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||||
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||||
import org.hibernate.cache.spi.support.DomainDataRegionTemplate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -24,13 +23,14 @@ public class DomainDataRegionImpl extends DomainDataRegionTemplate {
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public DomainDataRegionImpl(
|
public DomainDataRegionImpl(
|
||||||
DomainDataRegionConfig regionConfig,
|
DomainDataRegionConfig regionConfig,
|
||||||
CachingRegionFactory regionFactory,
|
RegionFactoryTemplate regionFactory,
|
||||||
|
DomainDataStorageAccess domainDataStorageAccess,
|
||||||
CacheKeysFactory defaultKeysFactory,
|
CacheKeysFactory defaultKeysFactory,
|
||||||
DomainDataRegionBuildingContext buildingContext) {
|
DomainDataRegionBuildingContext buildingContext) {
|
||||||
super(
|
super(
|
||||||
regionConfig,
|
regionConfig,
|
||||||
regionFactory,
|
regionFactory,
|
||||||
new MapStorageAccessImpl(),
|
domainDataStorageAccess,
|
||||||
defaultKeysFactory,
|
defaultKeysFactory,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.cache;
|
package org.hibernate.cache.spi.support;
|
||||||
|
|
||||||
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.testing.cache;
|
package org.hibernate.cache.spi.support;
|
||||||
|
|
||||||
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
|
@ -25,11 +25,13 @@ import org.hibernate.cache.ehcache.ConfigSettings;
|
||||||
import org.hibernate.cache.ehcache.MissingCacheStrategy;
|
import org.hibernate.cache.ehcache.MissingCacheStrategy;
|
||||||
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||||
|
import org.hibernate.cache.spi.DomainDataRegion;
|
||||||
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
||||||
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
|
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
|
||||||
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
||||||
import org.hibernate.cache.spi.support.RegionNameQualifier;
|
import org.hibernate.cache.spi.support.RegionNameQualifier;
|
||||||
import org.hibernate.cache.spi.support.StorageAccess;
|
import org.hibernate.cache.spi.support.StorageAccess;
|
||||||
|
import org.hibernate.cache.spi.support.DomainDataRegionImpl;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
|
||||||
import static org.hibernate.cache.ehcache.ConfigSettings.EHCACHE_CONFIGURATION_RESOURCE_NAME;
|
import static org.hibernate.cache.ehcache.ConfigSettings.EHCACHE_CONFIGURATION_RESOURCE_NAME;
|
||||||
|
@ -65,6 +67,18 @@ public class EhcacheRegionFactory extends RegionFactoryTemplate {
|
||||||
return cacheKeysFactory;
|
return cacheKeysFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainDataRegion buildDomainDataRegion(
|
||||||
|
DomainDataRegionConfig regionConfig, DomainDataRegionBuildingContext buildingContext) {
|
||||||
|
return new DomainDataRegionImpl(
|
||||||
|
regionConfig,
|
||||||
|
this,
|
||||||
|
createDomainDataStorageAccess( regionConfig, buildingContext ),
|
||||||
|
cacheKeysFactory,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DomainDataStorageAccess createDomainDataStorageAccess(
|
protected DomainDataStorageAccess createDomainDataStorageAccess(
|
||||||
DomainDataRegionConfig regionConfig,
|
DomainDataRegionConfig regionConfig,
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* 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.ehcache.test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
|
||||||
|
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
|
||||||
|
import org.hibernate.testing.jta.TestingJtaBootstrap;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class EhcacheTransactionalCacheConcurrencyStrategyTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private SQLStatementInterceptor sqlStatementInterceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||||
|
sqlStatementInterceptor = new SQLStatementInterceptor( sfb );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
|
||||||
|
|
||||||
|
TestingJtaBootstrap.prepare( settings );
|
||||||
|
settings.put( Environment.TRANSACTION_COORDINATOR_STRATEGY, "jta" );
|
||||||
|
settings.put( Environment.CACHE_REGION_FACTORY, "ehcache" );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Parent.class,
|
||||||
|
Child.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Parent")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
public static class Parent {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
private List<Child> children = new ArrayList<Child>();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Child> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildren(List<Child> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
Child addChild() {
|
||||||
|
final Child c = new Child();
|
||||||
|
c.setParent( this );
|
||||||
|
this.children.add( c );
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Child")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
public static class Child {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
fetch = FetchType.LAZY
|
||||||
|
)
|
||||||
|
private Parent parent;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parent getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(Parent parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactional() {
|
||||||
|
Parent parent = new Parent();
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
for ( int i = 0; i < 2; i++ ) {
|
||||||
|
parent.addChild();
|
||||||
|
|
||||||
|
session.persist( parent );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
sqlStatementInterceptor.getSqlQueries().clear();
|
||||||
|
|
||||||
|
Parent _parent = session.find( Parent.class, parent.getId() );
|
||||||
|
|
||||||
|
assertEquals( 0, sqlStatementInterceptor.getSqlQueries().size() );
|
||||||
|
|
||||||
|
assertEquals( 2, _parent.getChildren().size() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
sqlStatementInterceptor.getSqlQueries().clear();
|
||||||
|
|
||||||
|
Parent _parent = session.find( Parent.class, parent.getId() );
|
||||||
|
|
||||||
|
assertEquals( 2, _parent.getChildren().size() );
|
||||||
|
|
||||||
|
assertEquals( 0, sqlStatementInterceptor.getSqlQueries().size() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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.internal;
|
||||||
|
|
||||||
|
import org.hibernate.cache.cfg.spi.CollectionDataCachingConfig;
|
||||||
|
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
|
||||||
|
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
|
||||||
|
import org.hibernate.cache.cfg.spi.EntityDataCachingConfig;
|
||||||
|
import org.hibernate.cache.cfg.spi.NaturalIdDataCachingConfig;
|
||||||
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||||
|
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
||||||
|
import org.hibernate.cache.spi.access.AccessType;
|
||||||
|
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||||
|
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||||
|
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
|
||||||
|
import org.hibernate.cache.spi.support.DomainDataRegionImpl;
|
||||||
|
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
|
||||||
|
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JCacheDomainDataRegionImpl extends DomainDataRegionImpl {
|
||||||
|
|
||||||
|
public JCacheDomainDataRegionImpl(
|
||||||
|
DomainDataRegionConfig regionConfig,
|
||||||
|
RegionFactoryTemplate regionFactory,
|
||||||
|
DomainDataStorageAccess domainDataStorageAccess,
|
||||||
|
CacheKeysFactory defaultKeysFactory,
|
||||||
|
DomainDataRegionBuildingContext buildingContext) {
|
||||||
|
super( regionConfig, regionFactory, domainDataStorageAccess, defaultKeysFactory, buildingContext );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected EntityDataAccess generateTransactionalEntityDataAccess(EntityDataCachingConfig entityAccessConfig) {
|
||||||
|
SecondLevelCacheLogger.INSTANCE.nonStandardSupportForAccessType(
|
||||||
|
getName(),
|
||||||
|
AccessType.TRANSACTIONAL.getExternalName(),
|
||||||
|
getRegionFactory().getClass().getSimpleName()
|
||||||
|
);
|
||||||
|
return super.generateTransactionalEntityDataAccess( entityAccessConfig );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NaturalIdDataAccess generateTransactionalNaturalIdDataAccess(NaturalIdDataCachingConfig accessConfig) {
|
||||||
|
SecondLevelCacheLogger.INSTANCE.nonStandardSupportForAccessType(
|
||||||
|
getName(),
|
||||||
|
AccessType.TRANSACTIONAL.getExternalName(),
|
||||||
|
getRegionFactory().getClass().getSimpleName()
|
||||||
|
);
|
||||||
|
return super.generateTransactionalNaturalIdDataAccess( accessConfig );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CollectionDataAccess generateTransactionalCollectionDataAccess(CollectionDataCachingConfig accessConfig) {
|
||||||
|
SecondLevelCacheLogger.INSTANCE.nonStandardSupportForAccessType(
|
||||||
|
getName(),
|
||||||
|
AccessType.TRANSACTIONAL.getExternalName(),
|
||||||
|
getRegionFactory().getClass().getSimpleName()
|
||||||
|
);
|
||||||
|
return super.generateTransactionalCollectionDataAccess( accessConfig );
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,11 +25,13 @@ import org.hibernate.cache.internal.DefaultCacheKeysFactory;
|
||||||
import org.hibernate.cache.jcache.ConfigSettings;
|
import org.hibernate.cache.jcache.ConfigSettings;
|
||||||
import org.hibernate.cache.jcache.MissingCacheStrategy;
|
import org.hibernate.cache.jcache.MissingCacheStrategy;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
import org.hibernate.cache.spi.CacheKeysFactory;
|
||||||
|
import org.hibernate.cache.spi.DomainDataRegion;
|
||||||
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
import org.hibernate.cache.spi.SecondLevelCacheLogger;
|
||||||
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
|
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
|
||||||
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
||||||
import org.hibernate.cache.spi.support.RegionNameQualifier;
|
import org.hibernate.cache.spi.support.RegionNameQualifier;
|
||||||
import org.hibernate.cache.spi.support.StorageAccess;
|
import org.hibernate.cache.spi.support.StorageAccess;
|
||||||
|
import org.hibernate.cache.spi.support.DomainDataRegionImpl;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,6 +62,18 @@ public class JCacheRegionFactory extends RegionFactoryTemplate {
|
||||||
return cacheKeysFactory;
|
return cacheKeysFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DomainDataRegion buildDomainDataRegion(
|
||||||
|
DomainDataRegionConfig regionConfig, DomainDataRegionBuildingContext buildingContext) {
|
||||||
|
return new JCacheDomainDataRegionImpl(
|
||||||
|
regionConfig,
|
||||||
|
this,
|
||||||
|
createDomainDataStorageAccess( regionConfig, buildingContext ),
|
||||||
|
cacheKeysFactory,
|
||||||
|
buildingContext
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DomainDataStorageAccess createDomainDataStorageAccess(
|
protected DomainDataStorageAccess createDomainDataStorageAccess(
|
||||||
DomainDataRegionConfig regionConfig,
|
DomainDataRegionConfig regionConfig,
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Cache;
|
||||||
|
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||||
|
import org.hibernate.boot.SessionFactoryBuilder;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
|
||||||
|
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
|
||||||
|
import org.hibernate.testing.jta.TestingJtaBootstrap;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class JCacheTransactionalCacheConcurrencyStrategyTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private SQLStatementInterceptor sqlStatementInterceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
|
||||||
|
sqlStatementInterceptor = new SQLStatementInterceptor( sfb );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true" );
|
||||||
|
|
||||||
|
TestingJtaBootstrap.prepare( settings );
|
||||||
|
settings.put( Environment.TRANSACTION_COORDINATOR_STRATEGY, "jta" );
|
||||||
|
settings.put( Environment.CACHE_REGION_FACTORY, "jcache" );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Parent.class,
|
||||||
|
Child.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Parent")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
public static class Parent {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
private List<Child> children = new ArrayList<Child>();
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Child> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildren(List<Child> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
Child addChild() {
|
||||||
|
final Child c = new Child();
|
||||||
|
c.setParent( this );
|
||||||
|
this.children.add( c );
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Child")
|
||||||
|
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
|
||||||
|
public static class Child {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(
|
||||||
|
fetch = FetchType.LAZY
|
||||||
|
)
|
||||||
|
private Parent parent;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parent getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(Parent parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransactional() {
|
||||||
|
Parent parent = new Parent();
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
for ( int i = 0; i < 2; i++ ) {
|
||||||
|
parent.addChild();
|
||||||
|
|
||||||
|
session.persist( parent );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
sqlStatementInterceptor.getSqlQueries().clear();
|
||||||
|
|
||||||
|
Parent _parent = session.find( Parent.class, parent.getId() );
|
||||||
|
|
||||||
|
assertEquals( 0, sqlStatementInterceptor.getSqlQueries().size() );
|
||||||
|
|
||||||
|
assertEquals( 2, _parent.getChildren().size() );
|
||||||
|
} );
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, session -> {
|
||||||
|
sqlStatementInterceptor.getSqlQueries().clear();
|
||||||
|
|
||||||
|
Parent _parent = session.find( Parent.class, parent.getId() );
|
||||||
|
|
||||||
|
assertEquals( 2, _parent.getChildren().size() );
|
||||||
|
|
||||||
|
assertEquals( 0, sqlStatementInterceptor.getSqlQueries().size() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import org.hibernate.cache.spi.CacheKeysFactory;
|
||||||
import org.hibernate.cache.spi.DomainDataRegion;
|
import org.hibernate.cache.spi.DomainDataRegion;
|
||||||
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
|
||||||
import org.hibernate.cache.spi.support.StorageAccess;
|
import org.hibernate.cache.spi.support.StorageAccess;
|
||||||
|
import org.hibernate.cache.spi.support.DomainDataRegionImpl;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -58,6 +59,7 @@ public class CachingRegionFactory extends RegionFactoryTemplate {
|
||||||
return new DomainDataRegionImpl(
|
return new DomainDataRegionImpl(
|
||||||
regionConfig,
|
regionConfig,
|
||||||
this,
|
this,
|
||||||
|
new MapStorageAccessImpl(),
|
||||||
cacheKeysFactory,
|
cacheKeysFactory,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue