From 6e2f943dc52c6b78fb655929bdcdc9a04a1ad915 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Sat, 9 Sep 2023 18:20:29 -0700 Subject: [PATCH] update hibernate example to use the preferred meta model generator --- examples/hibernate/build.gradle.kts | 13 ++ examples/hibernate/gradle/libs.versions.toml | 1 + .../caffeine/examples/hibernate/Queries.java | 39 ++++ .../examples/hibernate/Repository.java | 77 -------- .../hibernate/HibernateCacheTest.java | 174 +++++++++--------- gradle/libs.versions.toml | 6 +- 6 files changed, 145 insertions(+), 165 deletions(-) create mode 100644 examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Queries.java delete mode 100644 examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Repository.java diff --git a/examples/hibernate/build.gradle.kts b/examples/hibernate/build.gradle.kts index d1b591a776..047a1dab5e 100644 --- a/examples/hibernate/build.gradle.kts +++ b/examples/hibernate/build.gradle.kts @@ -1,9 +1,15 @@ +import org.gradle.plugins.ide.eclipse.model.Classpath +import org.gradle.plugins.ide.eclipse.model.SourceFolder + plugins { + eclipse `java-library` alias(libs.plugins.versions) } dependencies { + annotationProcessor(libs.hibernate.jpamodelgen) + implementation(libs.bundles.hibernate) implementation(libs.bundles.log4j2) implementation(libs.caffeine) @@ -27,3 +33,10 @@ tasks.withType().configureEach { languageVersion = java.toolchain.languageVersion } } + +eclipse.classpath.file.beforeMerged { + if (this is Classpath) { + val absolutePath = layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main") + entries.add(SourceFolder(relativePath(absolutePath), "bin/main")) + } +} diff --git a/examples/hibernate/gradle/libs.versions.toml b/examples/hibernate/gradle/libs.versions.toml index d371d6ff5d..9682fde19a 100644 --- a/examples/hibernate/gradle/libs.versions.toml +++ b/examples/hibernate/gradle/libs.versions.toml @@ -13,6 +13,7 @@ caffeine = { module = "com.github.ben-manes.caffeine:jcache", version.ref = "caf h2 = { module = "com.h2database:h2", version.ref = "h2" } hibernate-core = { module = "org.hibernate.orm:hibernate-core", version.ref = "hibernate" } hibernate-jcache = { module = "org.hibernate.orm:hibernate-jcache", version.ref = "hibernate" } +hibernate-jpamodelgen = { module = "org.hibernate.orm:hibernate-jpamodelgen", version.ref = "hibernate" } hibernate-hikaricp = { module = "org.hibernate.orm:hibernate-hikaricp", version.ref = "hibernate" } junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } log4j2-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j2" } diff --git a/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Queries.java b/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Queries.java new file mode 100644 index 0000000000..b378da2161 --- /dev/null +++ b/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Queries.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Ben Manes. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.benmanes.caffeine.examples.hibernate; + +import java.util.List; + +import org.hibernate.annotations.processing.Find; +import org.hibernate.annotations.processing.HQL; + +/** + * @author ben.manes@gmail.com (Ben Manes) + */ +public interface Queries { + + @Find + User getUser(long id); + + @Find + Project getProject(long id); + + @HQL("FROM Project WHERE id = :id") + Project findProject(long id); + + @Find + List findProjects(); +} diff --git a/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Repository.java b/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Repository.java deleted file mode 100644 index 3f7c8fa8be..0000000000 --- a/examples/hibernate/src/main/java/com/github/benmanes/caffeine/examples/hibernate/Repository.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2023 Ben Manes. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.benmanes.caffeine.examples.hibernate; - -import static java.util.Objects.requireNonNull; - -import java.util.List; - -import org.hibernate.SessionFactory; - -/** - * @author ben.manes@gmail.com (Ben Manes) - */ -public final class Repository { - private final SessionFactory sessionFactory; - - public Repository(SessionFactory sessionFactory) { - this.sessionFactory = requireNonNull(sessionFactory); - } - - public Project getProject(long id) { - return sessionFactory.fromSession(session -> session.get(Project.class, id)); - } - - public User getUser(long id) { - return sessionFactory.fromSession(session -> session.get(User.class, id)); - } - - public Project findProject(long id) { - return sessionFactory.fromSession(session -> - session.createQuery("FROM Project WHERE id = :id", Project.class) - .setParameter("id", id) - .uniqueResult()); - } - - public List findProjects() { - return sessionFactory.fromSession(session -> - session.createQuery("FROM Project", Project.class).list()); - } - - public void updateProject(long id, String name) { - sessionFactory.inTransaction(session -> { - var project = session.get(Project.class, id); - project.setName(name); - session.merge(project); - }); - } - - public void persist(User user, Project project, Skill skill) { - sessionFactory.inTransaction(session -> { - session.persist(project); - session.persist(skill); - session.persist(user); - }); - } - - public void evictProject(long projectId) { - sessionFactory.getCache().evictEntityData(Project.class, projectId); - } - - public void evictAll() { - sessionFactory.getCache().evictDefaultQueryRegion(); - } -} diff --git a/examples/hibernate/src/test/java/com/github/benmanes/caffeine/examples/hibernate/HibernateCacheTest.java b/examples/hibernate/src/test/java/com/github/benmanes/caffeine/examples/hibernate/HibernateCacheTest.java index 37a371998e..54c57b25e0 100644 --- a/examples/hibernate/src/test/java/com/github/benmanes/caffeine/examples/hibernate/HibernateCacheTest.java +++ b/examples/hibernate/src/test/java/com/github/benmanes/caffeine/examples/hibernate/HibernateCacheTest.java @@ -17,109 +17,111 @@ import static com.github.benmanes.caffeine.examples.hibernate.HibernateSubject.assertThat; +import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** * @author ben.manes@gmail.com (Ben Manes) */ public final class HibernateCacheTest { - SessionFactory sessionFactory; - Repository repository; - - @BeforeEach - public void beforeEach() { - sessionFactory = new Configuration().addAnnotatedClass(User.class) - .addAnnotatedClass(Skill.class).addAnnotatedClass(Project.class) - .buildSessionFactory(new StandardServiceRegistryBuilder().build()); - repository = new Repository(sessionFactory); - } - - @AfterEach - public void afterEach() { - sessionFactory.close(); - } @Test public void lookup() { - long projectId = createData("Ben", "Caffeine", "Hibernate"); - - // db hit - Project project = repository.getProject(projectId); - - // cache hit - project = repository.getProject(projectId); - assertThat(sessionFactory).hits(4).misses(0).puts(3); - - // cache hit due to project associations - repository.getUser(project.getAssignee().getId()); - assertThat(sessionFactory).hits(5).misses(0).puts(3); - - // cache hit due to only the project being explicitly evicted - repository.evictProject(projectId); - repository.getUser(project.getAssignee().getId()); - assertThat(sessionFactory).hits(6).misses(0).puts(3); - - // db hit - project = repository.getProject(projectId); - assertThat(sessionFactory).hits(6).misses(1).puts(4); + try (var sessionFactory = newSessionFactory()) { + long projectId = sessionFactory.fromTransaction(session -> + createData(session, "Ben", "Caffeine", "Hibernate")); + + // db hit + var project = sessionFactory.fromSession(session -> Queries_.getProject(session, projectId)); + + // cache hit + sessionFactory.inSession(session -> Queries_.getProject(session, projectId)); + assertThat(sessionFactory).hits(4).misses(0).puts(3); + + // cache hit due to project associations + sessionFactory.fromSession(session -> + Queries_.getUser(session, project.getAssignee().getId())); + assertThat(sessionFactory).hits(5).misses(0).puts(3); + + // cache hit due to only the project being explicitly evicted + sessionFactory.getCache().evict(Project.class, projectId); + sessionFactory.fromSession(session -> + Queries_.getUser(session, project.getAssignee().getId())); + assertThat(sessionFactory).hits(6).misses(0).puts(3); + + // db hit + sessionFactory.inSession(session -> Queries_.getProject(session, projectId)); + assertThat(sessionFactory).hits(6).misses(1).puts(4); + } } @Test public void query() { - long projectId = createData("Ben", "Caffeine", "Hibernate"); - - // db hit - repository.findProject(projectId); - assertThat(sessionFactory).hits(1).misses(0).puts(3); - - // cache hit - repository.findProject(projectId); - assertThat(sessionFactory).hits(2).misses(0).puts(3); - - // db hit - repository.findProjects(); - assertThat(sessionFactory).hits(3).misses(0).puts(3); - - // cache hit - repository.findProjects(); - assertThat(sessionFactory).hits(4).misses(0).puts(3); - - // db hit - repository.evictAll(); - repository.findProject(projectId); - assertThat(sessionFactory).hits(5).misses(0).puts(3); - - // query cache hit - repository.findProject(projectId); - assertThat(sessionFactory).hits(6).misses(0).puts(3); - - // db hit - repository.findProjects(); - assertThat(sessionFactory).hits(7).misses(0).puts(3); - - // cache hit - repository.findProjects(); - assertThat(sessionFactory).hits(8).misses(0).puts(3); - - // automatically evicts project-related queries in the cache - repository.updateProject(projectId, "Updated"); - assertThat(sessionFactory).hits(10).misses(0).puts(4); - - // db hit - repository.findProject(projectId); - assertThat(sessionFactory).hits(11).misses(0).puts(4); + try (var sessionFactory = newSessionFactory()) { + long projectId = sessionFactory.fromTransaction(session -> + createData(session, "Ben", "Caffeine", "Hibernate")); + + // db hit + sessionFactory.inSession(session -> Queries_.findProject(session, projectId)); + assertThat(sessionFactory).hits(1).misses(0).puts(3); + + // cache hit + sessionFactory.inSession(session -> Queries_.findProject(session, projectId)); + assertThat(sessionFactory).hits(2).misses(0).puts(3); + + // db hit + sessionFactory.inSession(session -> Queries_.findProjects(session)); + assertThat(sessionFactory).hits(3).misses(0).puts(3); + + // cache hit + sessionFactory.inSession(session -> Queries_.findProjects(session)); + assertThat(sessionFactory).hits(4).misses(0).puts(3); + + // db hit + sessionFactory.getCache().evictDefaultQueryRegion(); + sessionFactory.inSession(session -> Queries_.findProject(session, projectId)); + assertThat(sessionFactory).hits(5).misses(0).puts(3); + + // query cache hit + sessionFactory.inSession(session -> Queries_.findProject(session, projectId)); + assertThat(sessionFactory).hits(6).misses(0).puts(3); + + // db hit + sessionFactory.inSession(session -> Queries_.findProjects(session)); + assertThat(sessionFactory).hits(7).misses(0).puts(3); + + // cache hit + sessionFactory.inSession(session -> Queries_.findProjects(session)); + assertThat(sessionFactory).hits(8).misses(0).puts(3); + + // automatically evicts project-related queries in the cache + sessionFactory.inTransaction(session -> { + var project = Queries_.getProject(session, projectId); + project.setName("Updated"); + session.merge(project); + }); + assertThat(sessionFactory).hits(10).misses(0).puts(4); + + // db hit + sessionFactory.inSession(session -> Queries_.findProject(session, projectId)); + assertThat(sessionFactory).hits(11).misses(0).puts(4); + + // db hit + sessionFactory.inSession(session -> Queries_.findProjects(session)); + assertThat(sessionFactory).hits(12).misses(0).puts(4); + } + } - // db hit - repository.findProjects(); - assertThat(sessionFactory).hits(12).misses(0).puts(4); + private static SessionFactory newSessionFactory() { + return new Configuration().addAnnotatedClass(User.class) + .addAnnotatedClass(Skill.class).addAnnotatedClass(Project.class) + .buildSessionFactory(new StandardServiceRegistryBuilder().build()); } - private long createData(String userName, String projectName, String skillName) { + private long createData(Session session, String userName, String projectName, String skillName) { var project = new Project(); var skill = new Skill(); var user = new User(); @@ -133,7 +135,9 @@ private long createData(String userName, String projectName, String skillName) { skill.setName(skillName); - repository.persist(user, project, skill); + session.persist(project); + session.persist(skill); + session.persist(user); return project.getId(); } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c4f9820119..d1040c669b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] asm = "9.5" -auto-value = "1.10.3" +auto-value = "1.10.4" awaitility = "4.2.0" bcel = "6.6.1" bnd = "6.4.0" @@ -11,7 +11,7 @@ checker-framework = "3.38.0" checkstyle = "10.12.3" coherence = "22.06.2" commons-collections4 = "4.4" -commons-compress = "1.23.0" +commons-compress = "1.24.0" commons-io = "2.13.0" commons-lang3 = "3.13.0" commons-math3 = "3.6.1" @@ -87,7 +87,7 @@ tcache = "2.0.1" testng = "7.8.0" truth = "1.1.5" univocity-parsers = "2.9.1" -versions = "0.47.0" +versions = "0.48.0" xerces = "2.12.2" xstream = "1.4.20" xz = "1.9"