【问题标题】:Partial Objects in EbeanEbean 中的部分对象
【发布时间】:2023-03-22 17:50:01
【问题描述】:

我正在尝试在 Java Play 中使用 Ebean 2.3.3 查询部分对象!框架 2.2.1。例如,要从instance_config 表中获取仅包含字段idhostpublicKey 的记录列表,我使用以下命令:

List<InstanceConfig> tests = Ebean.find(InstanceConfig.class)
                    .select("host,publicKey")
                    .where().eq("accountId", accountId).ne("host", "")
                    .findList();

这会产生以下 sql 查询,这是我所期望的:

[debug] c.j.b.PreparedStatementHandle - select t0.id as c0, t0.host as c1, 
            t0.public_key as c2 from instance_config t0 where t0.account_id = xxxxxxxxxx 
            and t0.host <> '' 

但是,相同的代码也会为正在查询的表中的每条记录生成此查询:

    [debug] c.j.b.PreparedStatementHandle - select t0.id as c0, t0.host as c1, 
           t0.public_key as c2, t0.private_key as c3, t0.created_by as c4,
           t0.account_id as c5 from instance_config t0 where t0.id = xx  

从服务器返回的输出包含完整的对象,以及所有的字段。

我猜这些查询与 Ebean 对部分对象所做的 Lazy Loading 有关吗?

我在SO question 中发现绕过延迟加载的一种方法是一起绕过 Ebean 并使用标准 JDBC 接口来执行查询。这个问题是几年前的问题,我想重新发布,问这个解决方案是否仍然准确?

【问题讨论】:

    标签: java playframework ebean


    【解决方案1】:

    很难说出您的具体问题是什么,但出于性能原因,通常您希望使用部分对象查询,并且通常在执行此操作时避免延迟加载。所以在你的情况下,也许你应该简单地从你的第一个查询中删除 select() 子句。

    延迟加载并不总是很糟糕,但在您的情况下,如果您想避免它,只需删除 select 子句,然后所有属性都将加载到原始查询中。

    现在在带有摘要级别日志记录(“org.avaje.ebean.SUM”上的调试级别)的日志中,例如:

    ... txn[2005] select t0.id c0 from be_customer t0; --bind()
    ... txn[2005] FindMany type[Customer] origin[5NLfz.CdTSLn.BvQ020] exeMicros[0] rows[0] name[] predicates[] bind[]
    ... txn[2006] select t0.id c0, t0.inactive c1, t0.name c2, t0.registered c3, t0.comments c4, t0.version c5, t0.when_created c6, t0.when_updated c7, t0.billing_address_id c8, t0.shipping_address_id c9 from be_customer t0 where t0.id = ?  ; --bind(1)
    ... txn[2006] FindMany mode[+lazy] type[Customer] origin[5NLfz.CdTSLn.BvQ020] lazyLoadProp[name] load[path:null batch:1] exeMicros[1079] rows[1] name[] predicates[] bind[1]
    

    在最后的日志条目中:

    • +lazy : 这是一个延迟加载查询
    • LazyLoadProp[name]:这是触发延迟加载的读取属性
    • origin[5NLfz.CdTSLn.BvQ020] :这标识了延迟加载相关的原始查询

    现在,并非所有延迟加载都不好,但在您的情况下,我们可以看到您的表不是很宽(延迟加载查询中没有那么多列)但我们不知道类型(那里有任何大的 varchar 列ETC)。我猜测并说您可能应该删除 select() 子句。

    如果您为“org.avaje.ebean.SUM”设置了 DEBUG 日志级别,那么您可以查找 +lazy 查询,检查它们关联的原始查询,并查看您是否/在哪里可以做得更好。

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      只要不访问任何其他字段,您就可以继续使用 Ebean。

      您在日志中看到的第二个查询会在您访问返回对象中已存在的任何字段时立即执行。这似乎是 Ebean 默认的延迟加载行为。

      我遇到了同样的问题,Ebean 在使用Json.toJson() 转换我的查询结果后加载了所有字段,这是访问我模型的所有字段以创建 JSON 对象。

      我通过手动操作结果解决了这个问题,确保不访问我在select 中获取的字段之外的任何其他字段。

      例如:

      List<InstanceConfig> tests = Ebean.find(InstanceConfig.class)
                      .select("host,publicKey")
                      .where().eq("accountId", accountId).ne("host", "")
                      .findList();
      // Accessing fields
      String host = tests.get(0).host; // Doesn't trigger a new query
      String publicKey = tests.get(0).publicKey; // Doesn't trigger a new query
      String otherField = tests.get(0).otherField; // This will trigger a query
      

      有关此主题的 Ebean 文档:http://ebean-orm.github.io/docs/query/features#lazy_loading

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多