I have seen lots of different guides for enabling second-level caching with Hibernate, all either out of date or with errors that are not described with a fix.
Currently, this is my setup:
My build.sbt
libraries for Hibernate
:
"org.hibernate.orm" % "hibernate-core" % "6.6.3.Final",
"org.hibernate.validator" % "hibernate-validator" % "8.0.0.Final",
"org.glassfish" % "jakarta.el" % "5.0.0-M1" % Test,
"io.agroal" % "agroal-pool" % "2.5",
"org.hibernate.orm" % "hibernate-agroal" % "6.4.4.Final",
"com.mysql" % "mysql-connector-j" % "9.1.0",
"jakarta.el" % "jakarta.el-api" % "6.0.1",
"com.sun.el" % "el-ri" % "3.0.4",
"jakarta.el" % "jakarta.el-api" % "6.0.1",
"org.hibernate.orm" % "hibernate-jcache" % "6.6.9.Final",
"org.ehcache" % "ehcache" % "3.10.8",
"org.hibernate.orm" % "hibernate-ehcache" % "6.0.0.Alpha7",
"jakarta.xml.bind" % "jakarta.xml.bind-api" % "4.0.2",
"org.glassfish.jaxb" % "jaxb-runtime" % "4.0.5",
"jakarta.transaction" % "jakarta.transaction-api" % "2.0.1",
Database creation:
val config = new Configuration()
.addAnnotatedClass(classOf[Server])
.addAnnotatedClass(classOf[Chat])
.addAnnotatedClass(classOf[User])
.setProperty(JAKARTA_JDBC_URL, "jdbc:mysql://localhost:3306/hydra_data")
.setProperty(JAKARTA_JDBC_USER, sqlUser)
.setProperty(JAKARTA_JDBC_PASSWORD, sqlPass)
.setProperty("hibernate.hbm2ddl.auto", "create")
// use Agroal connection pool
.setProperty("hibernate.agroal.maxSize", "20")
.setProperty("hibernate.hbm2ddl.auto", "update")
.setProperty("hibernate.cache.use_query_cache", true)
.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory")
.setProperty("hibernate.javax.cache.provider", "org.ehcache.jsr107.EhcacheCachingProvider")
sessionFactory = Option(config.buildSessionFactory())
Currently, I have this error:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/transaction/SystemException
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:578)
at java.base/java.lang.Class.forName(Class.java:557)
at org.jboss.logging.Logger.doGetMessageLogger(Logger.java:2562)
at org.jboss.logging.Logger.getMessageLogger(Logger.java:2530)
at org.jboss.logging.Logger.getMessageLogger(Logger.java:2516)
at org.hibernate.cache.ehcache.internal.EhCacheMessageLogger.<clinit>(EhCacheMessageLogger.java:31)
at org.hibernate.cache.ehcache.internal.EhcacheRegionFactory.<clinit>(EhcacheRegionFactory.java:46)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized0(Native Method)
at java.base/jdk.internal.misc.Unsafe.ensureClassInitialized(Unsafe.java:1161)
at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.ensureClassInitialized(MethodHandleAccessorFactory.java:340)
at java.base/jdk.internal.reflect.MethodHandleAccessorFactory.newConstructorAccessor(MethodHandleAccessorFactory.java:103)
at java.base/jdk.internal.reflect.ReflectionFactory.newConstructorAccessor(ReflectionFactory.java:173)
at java.base/java.lang.reflect.Constructor.acquireConstructorAccessor(Constructor.java:548)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:498)
at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:132)
at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:259)
at java.base/java.lang.Class.newInstance(Class.java:804)
at org.hibernate.cache.internal.StrategyCreatorRegionFactoryImpl.create(StrategyCreatorRegionFactoryImpl.java:62)
at org.hibernate.cache.internal.StrategyCreatorRegionFactoryImpl.create(StrategyCreatorRegionFactoryImpl.java:23)
at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:240)
at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:189)
at org.hibernate.cache.internal.RegionFactoryInitiator.resolveRegionFactory(RegionFactoryInitiator.java:96)
at org.hibernate.cache.internal.RegionFactoryInitiator.initiateService(RegionFactoryInitiator.java:47)
at org.hibernate.cache.internal.RegionFactoryInitiator.initiateService(RegionFactoryInitiator.java:32)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215)
at org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl.<init>(MetadataBuilderImpl.java:705)
at org.hibernate.boot.internal.MetadataBuilderImpl.<init>(MetadataBuilderImpl.java:139)
at org.hibernate.boot.MetadataSources.getMetadataBuilder(MetadataSources.java:164)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:899)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:999)
at database.Database.init(Database.scala:79)
at database.DatabaseUtil$.getInstance(Database.scala:29)
at core.Main$.main(Main.scala:34)
at core.Main.main(Main.scala)
Caused by: java.lang.ClassNotFoundException: javax.transaction.SystemException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:528)
... 38 more
Which, from what I've read, should be fixed with the import of jakarta.transaction-api
, but it is not.
Can someone provide complete steps for enabling caching properly please?
So it turns out it was a combination of mismatched packages and some errors in my config.
Working imports:
// Hibernate stuff
"org.hibernate.orm" % "hibernate-core" % "6.6.3.Final",
"org.hibernate.orm" % "hibernate-jcache" % "6.6.3.Final",
"org.hibernate.validator" % "hibernate-validator" % "8.0.0.Final",
"io.agroal" % "agroal-pool" % "2.5",
"org.hibernate.orm" % "hibernate-agroal" % "6.6.3.Final",
"com.mysql" % "mysql-connector-j" % "9.2.0",
"jakarta.el" % "jakarta.el-api" % "6.0.1",
"com.sun.el" % "el-ri" % "3.0.4",
"jakarta.el" % "jakarta.el-api" % "6.0.1",
"org.ehcache" % "ehcache" % "3.10.8",
"jakarta.xml.bind" % "jakarta.xml.bind-api" % "4.0.2",
"org.glassfish.jaxb" % "jaxb-runtime" % "4.0.5",
"jakarta.transaction" % "jakarta.transaction-api" % "2.0.1",
I ensured the versions of hibernate
packages and ehcache
are compatible.
And the hibernate
config:
val config = new Configuration()
.addAnnotatedClass(classOf[Server])
.addAnnotatedClass(classOf[Chat])
.addAnnotatedClass(classOf[User])
.setProperty(JAKARTA_JDBC_URL, "jdbc:mysql://localhost:3306/hydra_data")
.setProperty(JAKARTA_JDBC_USER, sqlUser)
.setProperty(JAKARTA_JDBC_PASSWORD, sqlPass)
.setProperty("hibernate.hbm2ddl.auto", "create")
// use Agroal connection pool
.setProperty("hibernate.agroal.maxSize", "20")
.setProperty("hibernate.hbm2ddl.auto", "update")
.setProperty("hibernate.cache.use_second_level_cache", true)
.setProperty("hibernate.cache.use_query_cache", true)
.setProperty("hibernate.cache.region.factory_class", "org.hibernate.cache.jcache.JCacheRegionFactory")
.setProperty("hibernate.javax.cache.provider", "org.ehcache.jsr107.EhcacheCachingProvider")