Ebean中的部分对象

时间:2015-07-27 23:11:44

标签: java playframework ebean

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

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中发现,绕过Lazy Loading的一种方法是一起绕过Ebean并使用标准的JDBC接口来执行查询。问题是几年前,我想重新询问这个解决方案是否仍然准确?

2 个答案:

答案 0 :(得分:1)

很难说明你的问题具体是什么,但通常你想要出于性能原因使用部分对象查询,并且通常在执行时避免延迟加载。因此,在您的情况下,您可能只需从第一个查询中删除select()子句。

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

现在在带有摘要级别日志记录的日志中(DEBUG级别为&#34; org.avaje.ebean.SUM&#34;)例如:

... 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列)在那里等)。我猜测并说你可能只需删除select()子句。

如果你有&#34; org.avaje.ebean.SUM&#34;的DEBUG日志级别。然后你可以查找+ lazy查询,检查它们相关的原始查询,并查看是否/可以做得更好。

希望这有帮助。

答案 1 :(得分:0)

只要您不访问任何其他字段,就可以继续使用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