EclipseLink 对JPA Query 实现的优化实现

今天同事碰到一个JPA Query 的问题, 在业务上我们有4个entity

 

CustomerSetType

       一对多个  CustomerSet  

CustomerSet

       多对一   CustomerSetType,  多对一 master  CustomerSet,  一对多  Customer

Customer

       一对多 Client

Client

 

 

由于业务性质就不具体贴出代码, 基本的实体间关系就如上述所说。  我们使用的是ElipseLink 的 JPA 实现. 在配置多对一, 一对多的  FetchType 都是默认的设置。 也就是说多对一默认的fetchType 是 Eager,  一对多的是Lazy。 

 

现在有一个NameQuery :   select cs  from CustomerSet cs where  cs.customerType.code = 'ABC'

 

写一个简单的unit test 跑跑, 从log 看到EclipseLink  大约用了   700 多个 query。  汗一个,  难怪客户不爽, 要求改进。  

 

改进的思路是使用 JPA query 的Hint , 只改query的配置, 保持代码annotation的配置不变还是默认方式。  这样基本上以前的代码就不需要改动。  

 

具体的进行过程中碰到的问题:

 

   1,  好像EclipseLink 在 NamedQuery 中 采用标准的JPA lint  名字 , 比如 

             <hint name="LEFT_FETCH" value="cs.customerSetType"></hint>

          从log 的结果来看没有具体效果

 

    2,  只好到EclipseLink  官方网站 找线索,  突然想起上次做查询 需要 Cursor 的时候用Hint 的时候 也碰到一个问题  标准的JPA hint name  它就是不支持。  根据这个提示找到   一个 hint name :  eclipselink.left-join-fetch,  为什么要用到  left join 呢? 因为这个CustomerSet 下面可能是还没有关联上 Customer , 同理 Customer 还没有关联上 Client 的。  CustoomerSet,Customer 到Client 有3级, 我们只需要配置 fetch join 到 cs.customerlist.clientlist , 从输出的sql 可以看到有两个 left join , 一个是  customer set left join customer, 一个是 left join client。 再看sql 已经减少到 几十个。为什么还还有这么多呢? 在customer set 实体上一个有 3个一对多的关系,  我们现在只处理掉一个,  还有两个呢, 它到 customer set type,  它自身join 的 master customer set。  如法炮制, 但是它们俩就不需要 left join 了,  eclipselink.join-fetch  搞定。

   再来看输出的sql  只有 4个了, 主要是因为它自己的级联出来的 master customer set 需要再去搞定 type name 啥的, 基本上没有办法再精简了。

 

 回头想想, 如果现在的OR Mapping 能做到这个效果,效率不比我们自己native sql 出来再拼装 对象的方式差吧。 做个记号,要去down 个 EclipseLink 的代码来看看它的实现补补课了。  

 

 

 

 

 

 

 

你可能感兴趣的:(eclipse)