【问题标题】:JPA Native Query with call to Oracle function returns the same object in different calls in same Transaction context调用 Oracle 函数的 JPA 本机查询在同一事务上下文中的不同调用中返回相同的对象
【发布时间】:2016-06-29 15:54:02
【问题描述】:

我在托管事务上下文中执行查询时遇到问题(使用 JTA 事务工厂)

在请求的整个执行过程中,查询应该被执行两次:第一次从数据库中获取默认值;第二次,使用不同的参数运行,它应该返回具有不同值的不同对象。

查询本身会调用 Oracle 数据库中的函数,如下所示:

SELECT attr1, attr2, attr3
FROM TABLE(package.function (
    param1 => :param1,
    param2 => :param2,
    param3 => :param3))

执行查询的方法(必须使用不同的参数执行两次)类似于:

public MyEntity getMyEntity(Map<String,String> params) {
    String sql = getQuery(); // gets the string of the aforementioned query
    Query query = getEntityManager().createNativeQuery(sql, MyEntity.class);

    query.setParameter("param1", params.get("param1"));
    query.setParameter("param2", params.get("param2"));
    query.setParameter("param3", params.get("param3"));

    return (MyEntity) query.getSingleResult();
}

问题是在请求的执行过程中,第一次调用这个方法时,它返回了一个正确的MyEntity对象。然而,第二次调用函数时,函数getMyEntity 错误地返回了同一个对象(他的 Java 对象引用与第一个对象的引用相同),尽管调用它的参数不同。

这似乎是一个缓存问题;所以我明确地将以下属性添加到我的persistence.xml 文件中

<property name="hibernate.cache.provider_class" value="org.hibernate.cache.SingletonEhCacheProvider"/>
<property name="hibernate.cache.use_second_level_cache" value="false"/>
<property name="hibernate.cache.use_query_cache" value="false"/>

并设置查询提示

query.setHint(QueryHints.CACHEABLE, false);

但问题仍然存在。

我想问一下我是否遗漏了什么以及是否有办法解决这个问题。

注意:代码是项目的一部分,它是将旧应用程序移植到基于 RESTful API 的新版本,因此不能更改代码的逻辑结构。

【问题讨论】:

    标签: sql oracle jpa jakarta-ee caching


    【解决方案1】:

    JPA 规范强制

    getEntityManager().createNativeQuery(sql, MyEntity.class);
    

    返回 MyEntity 的托管实例。您正在导致由第一个查询构建的 MyEntity 实例被管理和跟踪以进行更改,当然,它的身份将被管理。加载实体后,每次查询该实例时都会返回相同的实例。因此,当您的下一个查询返回具有相似 ID 值的行时,将返回前一个实体。

    一些选项,具体取决于您的提供商:

    1. 清除缓存。如果您在 交易,否则您可能需要将实体从 共享缓存。
    2. 强制刷新。 EclipseLink 有一个刷新查询 提示如果在第二个查询中使用,将导致实体 重新加载了第二组数据
    3. 不要使用托管实体 对于更适合原始数据的函数。如果你想要的一切 是数据的 DTO,使用概述的构造函数选项 here

    选项 3 对我来说更有意义,因为损坏缓存和从其他查询返回的对象的风险较小。

    【讨论】:

    • 非常感谢。选项 1 对我来说非常有效,有效地删除了缓存。我没有尝试其他两种方法,因为我试图在不改变太多结构的情况下符合旧的遗留代码。
    猜你喜欢
    • 1970-01-01
    • 2021-12-27
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多