En utilisant JBoss Cache, il était possible de stocker le cache entity
et le cache query
dans la même région de cache sans aucun problème. Mais une fois migré à wildfly 10 (avec infinispan comme 2LC), il semble y avoir un problème.Hibernate Infinispan 2LC: cache de requête et cache d'entité dans la même région de cache
J'ai fourni la région de cache pour l'entité comme ci-dessous.
@Entity
@Cacheable
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,
region="regionA")
public class EntityXYZ{
et le cache de requête comme
entManager.createQuery(
"....")
.setHint("org.hibernate.cacheable", true)
.setHint("org.hibernate.cacheRegion", "regionA").getResultList();
Il est important de noter que le query
ci-dessus contient aussi le entities
qui se sont déclarés comme cacheable
et a même région de cache regionA
.
Maintenant, lors de l'exécution, il y a cette erreur. Je soupçonne que c'est dû au conflit car ils sont stockés dans la même région et il essaye d'aller chercher l'identifiant d'objet qui renvoie un autre objet. Mais quelqu'un peut-il jeter de la lumière. Est-ce vraiment le cas? et expliquer plus sur l'erreur?
Mais la même chose fonctionne dans le cache JBoss dans JBoss 5
. Est-ce que infinispan
gère différemment? Ou est-ce problème Hibernate
?
ERROR [org.jboss.as.ejb3.invocation] (default task-8) WFLYEJB0034: EJB Invocation failed on component... javax.ejb.EJBTransactionRolledbackException: Object [id=4] was not of the specified subclass [ com.abc.xyz] : loaded object was of wrong class class com.abc.yyy
at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:159)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:256)
[org.hibernate.event.internal.DefaultLoadEventListener] (default task-8) HHH000327: Error performing load command : org.hibernate.WrongClassException: Object [id=4] was not of the specified subclass [com.abc.xyz] : loaded object was of wrong class class com.abc.yyy
MISE À JOUR:
Les entitymanager
tente de charger dans les différents appels de ces classes 2 (dans la même cache partagée région 2LC) qui a @id
comme int
. Comme Flavius l'a souligné, le id=4
semble être commun entre 2 classes.
Lors de l'ajout ci-dessous de la configuration à persistence.xml, une erreur de démarrage s'est produite.
persistence.xml
<property name="hibernate.cache.keys_factory" value="default" />
erreur
javax.persistence.PersistenceException: [PersistenceUnit: app-entity] Unable to build Hibernate SessionFactory
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:179)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:121)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:193)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: app-entity] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882)
at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44)
at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:161)
... 7 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:242)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
... 9 more
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [default] as strategy [org.hibernate.cache.spi.CacheKeysFactory]
at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:113)
at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:162)
at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:126)
MISE A JOUR 2
J'ai changé pour fournir le default
à FQN
exacte, mais il ne ne fonctionne pas. L'erreur n'est pas correcte car la classe est l'implémentation de la classe spécifiée.
<property name="hibernate.cache.keys_factory" value="org.hibernate.cache.internal.DefaultCacheKeysFactory" />
erreur:
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.spi.CacheImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:264)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:228)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:207)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:242)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
... 9 more
Caused by: java.lang.ClassCastException: org.hibernate.cache.internal.DefaultCacheKeysFactory cannot be cast to org.hibernate.cache.spi.CacheKeysFactory
at org.hibernate.cache.infinispan.InfinispanRegionFactory.determineCacheKeysFactory(InfinispanRegionFactory.java:427)
at org.hibernate.cache.infinispan.InfinispanRegionFactory.start(InfinispanRegionFactory.java:378)
at org.hibernate.internal.CacheImpl.<init>(CacheImpl.java:49)
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:28)
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:20)
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:46)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:254)
Selon JIRA, il semble que le problème avec DefaultCacheKeysFactory a été corrigé dans 5.0.12, 5.1.3 et 5.2.5. Habituellement, vous devriez pouvoir mettre à jour manuellement le module hibernate-orm de WF à 5.0.12 (comme pour toute version micro). –
Merci. S'il n'y a pas de gain de performance dû à la région du cache partagé, alors je m'en tiendrai aux meilleures pratiques. – ulab