问题:
I have a common database that is used by two different applications (different technologies, different deployment servers, they just use the same database).
Let's call t...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
I have a common database that is used by two different applications (different technologies, different deployment servers, they just use the same database).
Let's call them application #1
and application #2
.
Suppose we have the following scenario:
- the database contains a table called items (doesn't matter its content)
application #2
is developed in Spring Boot and it is mainly used just for reading data from the database
application #2
retrieves an item from the database
application #1
changes that item
application #2
retrieves the same item again, but the changes are not visible
What I understood by reading a lot of articles:
- when
application #2
retrieves the item, Hibernate stores it in the first level cache
- the changes that are done to the item by
application #1
are external changes and Hibernate is unaware of them, and thus, the cache is not updated (same happens when you do a manual change in the database)
- you cannot disable Hibernate's first level cache.
So, my question is, can you force Hibernate into refreshing the entities every time they are read (or make it go into the database) without explicitly calling em.refresh(entity)
? The problem is that the business logic module from application1
is used as a dependency in application1
so I can only call service methods (i.e. I don't have access to the entityManager
or session
references).
回答1:
Hibernate L1 cache is roughly equivalent to a DB transaction when you run in a repeatable-read level isolation. Basically, if you read/write some data, the next time you query in the context of the same session, you will get the same data. Further, within the same process, sessions run independent of each other, which means 2 session are looking at different data in the L1 cache.
If you use repeatable read or less, then you shouldn't really be concerned about the L1 cache, as you might run into this scenario regardless of the ORM (or no ORM).
I think you only need to think about the L2 cache here. The L2 cache is what stores data and assumes only hibernate is accessing the DB, which means that if some change happens in the DB, hibernate might not know about it. If you just disable the L2 cache, you are sorted.
Further reading - Short description of hibernate cache levels
回答2:
Well, if you cannot access hibernate session you are left with nothing. Any operations you want to do requires session access. For instance you can remove entity from cache after reading it like this:
session.evict(entity);
or this
session.clear();
but first and foremost you need a session. Since you calling only services you need to create service endpoints clearing session cache after serving them or modify existing endpoints to do that.
回答3:
回答4:
You can force to start a new transaction, so in this manner hibernate will not be read from the cache and it will redo the read from the db.
You can annotate your function in this manner
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
Requesting a new transaction, the system will generation a new hibernate session, so the data will not be in the cache.