-
Notifications
You must be signed in to change notification settings - Fork 69
ISPN-8024 Preview Hibernate cache local tutorial #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I plan to add more simple tutorials:
|
One option I was considering is that before any operation is executed, reset the statistics, so that the changes in values are more visible and require less mental exercise for the reader. Thoughts? |
Added a new commit that makes the tutorial expectations more predictable. See comments in commit log and code. Also, on top of the stats reset before each operation, I'm also considering adding some assertions so that we can quickly verify it's all working fine (as opposed to having to read the log messages). I think the log messages are still useful for the reader. I think we should have both message information and assertions so that even if assertions are disabled, the reader can verify manually the expected counts. |
EntityManagerFactory emf = Persistence.createEntityManagerFactory("events"); | ||
|
||
// Persist 3 entities, stats should show 3 second level cache puts | ||
SecondLevelCacheStatistics cacheStats = persistEntities(emf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning statistics from a write method looks ugly. Fetch stats independently.
} | ||
|
||
private static SecondLevelCacheStatistics getCacheStatistics( | ||
String regionName, EntityManager em) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dislike passing EntityManager
into a method that does not use the EntityManager
. Pass EntityManagerFactory
and call unwrap(SessionFactory.class)
on that.
private static SecondLevelCacheStatistics findEntity(EntityManagerFactory emf) { | ||
EntityManager em = emf.createEntityManager(); | ||
try { | ||
Event event = em.find(Event.class, 1L); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relying on auto-generated ids does not seem stable (especially since you need to provide the L
suffix), but probably good enough for tutorial. I would pass 1L
as a parameter, though, to be symmetric with updateEntity
.
tx.begin(); | ||
|
||
Event event = em.find(Event.class, id); | ||
String newName = "Caught a Snorlax!!"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused var
private static void evictEntity(EntityManagerFactory emf) { | ||
EntityManager em = emf.createEntityManager(); | ||
try { | ||
em.getEntityManagerFactory().getCache().evict(Event.class, 1L); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1L
as param, same as findEntity
|
||
|
||
// Save cache-expiring entity, stats should show a second level cache put | ||
cacheStats = saveExpiringEntity(emf); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a bit surprising that cacheStats now belong to different entity cache.
* Added a short delay after deleting an entity so that there's a gap between the query invalidation and the query being cached. This makes the query afterwards not be considered out of date. * Added log4j2 dependency and configuration file for easy to generate easy to read TRACE logs for debugging. Java logging can do that but can't print thread names, so better to go with log4j2.
f506cc1
to
8f300f9
Compare
@rvansa I've fixed all of your concerns. What do you think of my suggestion to reset statistics to make changes more clear? I'm also considering adding Java assert calls so that if someone runs with |
@galderz I don't think resetting the statistics is necessary, but I don't have any objections. If you want to add those assertions, refactor One more thing about closing the |
Thx @rvansa! I'll try to apply statistics reset and see if that makes clearer. Yeah, I know it's not a test but using assert is free in this case, no need for dependency, so it offers an extra layer for little cost. Yeah, I'd do a refactor like the one you suggest. Yup, I'll try to use the try-with-resources. |
* It helps to see more clearly what are the effects of each JPA operation on the statistics, particularly when a JPA operation results in a count change of more than 1.
@rvansa I've pushed some new commits to add:
If this looks good, let's integrate it and I can start work on next case, local second level cache with Spring or Wildfly. |
return emf.unwrap(SessionFactory.class).getStatistics(); | ||
} | ||
|
||
private static void printfAssert(String format, long actual, int expected) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actual is long
, expected is int
} | ||
|
||
private static void findEntity(long id) { | ||
try(Session em = createEntityManagerWithStatsCleared()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking, there should be a space between try
and (
private static Session createEntityManagerWithStatsCleared() { | ||
EntityManager em = emf.createEntityManager(); | ||
emf.unwrap(SessionFactory.class).getStatistics().clear(); | ||
return em.unwrap(Session.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that you should add a comment that EntityMangager
is not AutoCloseable
to explain why are you using a Session
instead... unwrap
to get stats is to-be-expected, but using it for EM looks hackish.
<arguments> | ||
<argument>-Djava.net.preferIPv4Stack=true</argument> | ||
<argument>-Djava.util.logging.config.file=src/main/resources/logging.properties</argument> | ||
<argument>-classpath</argument> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that you're missing -ea
switch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't add it since assertions are no longer needed to verify counts.
|
||
private static void printfAssert(String format, long actual, int expected) { | ||
System.out.printf(format, actual, expected); | ||
assert expected == actual : errorMsgAndCloseEntityManagerFactory(actual, expected); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side effect (closing emf) from assert message looks clunky... use rather if ... throw some exception
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Moving the code to simply throw exceptions and hence does not need assertions any more.
* Instead of having to rely on assertions, simply throw an exception when the expected effects do not happen. * Added javadoc to clarify Session unwrap call. * Minor formatting changes.
3969c9b
to
7a87f1e
Compare
@rvansa I've pushed changes to handle your last comments. |
I think we're good with this for now. I'm integrating and moving on to other examples. |
Preview PR for the first of the Hibernate cache provider tutorials.
This first tutorial is focused on using Hibernate cache provider in a standalone, single-node, environment.
The tutorial randomly shows different counts, which I need to debug further. Also, the PR uses a snapshot, so do not yet integrate it.
Let's just use this PR to get some feedback on the tutorial itself.