当非主要键查询时,使用JPA缓存结果的方法是什么?
我有一个JPA Entity Entitya
映射到表table_a
的数据,例如:
obj_id | ref_id |状态| ...
其中obj_id
是主要键,ref_id
是来自另一个表table_b
的外键,jpa未管理。
我需要能够:
返回与非主要密钥的给定值相关的所有行,例如
ref_id
:从table_a选择 * ref_id ='ref_id_1'
缓存来自((从1),所以在执行写作之前,我不会击中数据库。
在交易中写入(Update / Delete)期间,请读取所有行,包括(1)中的未命令数据:< / p>
代码:
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// Let's assume this returns 1 row
Transaction {
update('REF_ID_1', 'REF_ID_2');
// Fires: UPDATE TABLE_A SET REF_ID = 'REF_ID_2' WHERE REF_ID = 'REF_ID_1'
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// This should return 0 rows
}
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// If the transaction gets committed, this should return 0 rows
// If rolled back, should return 1 row
我尝试使用Eclipselink的实现JPA来映射实体,以table_a < / code>。 我正在使用对象(L2)缓存来通过主键缓存,然后使用查询缓存来缓存结果,由非主要密钥字段(例如
或ref_id
status> status> status
)查询。 。
来自
查询结果缓存未从 像对象缓存一样的应用。它应该仅用于缓存 只读对象,或者应该使用无效策略避免 缓存陈旧结果。在结果中对对象进行了更改 设置仍将被拾取,但是影响结果集的变化 (例如新的或更改的对象,应从 结果集)将不会被捡起。
此外,如果查询缓存不是用于缓存结果的正确方法,那么非主要密钥字段获得的缓存结果的方法是什么?
我找不到等于Spring Data的findall(示例&lt; s&gt;)
我可以在entitymanager
api中指定谓词 - 一切似乎都需要主要的钥匙。我尝试了criteriaquery
,但无法缓存其结果。
I have a JPA entity EntityA
mapped to a table TABLE_A
with data like:
OBJ_ID | REF_ID | STATUS | ...
where OBJ_ID
is the primary key and REF_ID
is a foreign key from another table TABLE_B
which is not managed by JPA.
I need to be able to:
Return all rows which relate to a given value of a non-primary key, say
REF_ID
:SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
Cache results from (1), so I do not hit the database until a write has been performed.
During write (UPDATE / DELETE) within a transaction, read back all rows including un-committed data as in (1):
Code:
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// Let's assume this returns 1 row
Transaction {
update('REF_ID_1', 'REF_ID_2');
// Fires: UPDATE TABLE_A SET REF_ID = 'REF_ID_2' WHERE REF_ID = 'REF_ID_1'
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// This should return 0 rows
}
fetchAllByRefId('REF_ID_1');
// Fires: SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
// If the transaction gets committed, this should return 0 rows
// If rolled back, should return 1 row
I tried to use Eclipselink's implementation of JPA to map the entity against TABLE_A
.
I am using the object (L2) cache to cache by primary key, and using the query cache to cache results queried by a non-primary key field such as REF_ID
or STATUS
.
From the documentation of Query Results cache:
The query results cache does not pick up committed changes from the
application as the object cache does. It should only be used to cache
read-only objects, or should use an invalidation policy to avoid
caching stale results. Committed changes to the objects in the result
set will still be picked up, but changes that affect the results set
(such as new or changed objects that should be added/removed from the
result set) will not be picked up.
Further, if the query cache is not the correct thing to use for caching the results, what is the way to cache results fetched by a non-primary key field?
I was not able to find an equivalent to Spring Data's findAll(Example<S>)
where I can specify a predicate, in the EntityManager
API - everything seems to require the primary key. I have tried CriteriaQuery
, but was unable to cache its results.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如DOC所述,查询缓存是一个查询结果缓存,该缓存存储数据库返回的结果。这些结果不是实体,因此它们不在单位工程或实体manager上下文中维护;一旦阅读,它们就会保持不变,直到清除为止。这并不是说您会恢复过时的数据;有一个单独的实体缓存仍可以使用,您可能需要配置它(默认情况下是打开)。这意味着,如果您执行
select *从table_a中select * where ref_id ='ref_id_1'
查询,它将缓存并返回匹配的行而不是击中数据库,但请使用实体缓存到返回实体对象。因此,它将返回所有具有ref_id ='ref_id_1'的平面实例,截至查询被缓存时。这也意味着如果查询结果非常陈旧,它可能会排除新实例或包含已删除的实例;从 eclipselink 2.5 可以根据所涉及的更改使查询缓存结果无效,这将导致您的查询从下一个执行中的数据库刷新。不过,您的问题似乎是必须如何使用查询缓存。 Eclipselink仅通过命名查询支持查询缓存。请参阅答案此处有关如何添加命名查询的详细信息。在春季,在尝试生成查询之前先使用方法名称查找。
因此
A query cache, as the doc states, is a query result cache storing the results the database returned. These results are not entities so they aren't maintained within a UnitOfWork or EntityManager context; once read in, they are unchanged until they are cleared. That isn't to say you will get stale data back; there is a separate entity cache that still gets used that you may need to configure (it is on by default). What that means is that if you execute a
SELECT * FROM TABLE_A WHERE REF_ID = 'REF_ID_1'
query, it will cache and return the rows that match up instead of hitting the database, but use the Entity cache to return the entity objects. So it will return all TableA instances that had a Ref_id = 'REF_ID_1' as of the time the query was cached, but if the entities exist in the entity cache, may show a different ref_id as well as any other state that might have since changed. This would also mean it might exclude new instances or include deleted ones if the query result is very stale; as of EclipseLink 2.5, EclipseLink can invalidate query cache results based on the changes involved, which will cause your query to refresh from the database on the next execution.Your issue though seems to be with how query caches must be used. EclipseLink only supports query caches through named queries. See the answer here for details on how to add named queries. In Spring, they are looked up using the method name first before it tries to generate a query.
So a
"TableA.fetchAllByRefId"
named query would get used on a TableARepository class method: