编程生活

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  113 随笔 :: 0 文章 :: 18 评论 :: 0 Trackbacks

在这,多次提到使用构造型查询,主要是我不想取出结果后再转型,这样,自己也实在太累了,因此,非常希望让openJPA一下就将结果做好,毕竟感觉上性能也要好过使用简单查询方式。

I.openJPA的构造型查询


openJPA在构造型查询方面好过其它几家,它支持三种方式:
1.通过反射注入,通过setXXX(字段名)注入到目标类(dto对象)的字段中
2.通过put方法,目标类(dto对象)需实现public void put(Object field, Object value)接口方法,然后openJPA的结果包装器调用此接口,将数据写到对象中
3.通过构造方法,目标类(dto对象)提供所需的构造函数,然后openJPA的结果包装器通过该构造函数实例化.
第1种方式最好,第3种方式最差,特别是对于查询结果比较多,做构造函数简直就是不可能的事
用第1种方式,虽然最好,但在openJPA0.9.6,0.9.7及1.0.0中对于使用JPQL这种方式均受到限制,缺省情况下openJPA提供的字段名是jpqlalias1,..,而你的DTO对象不可能定义为jpqlalias1,,这样的字段,这样就脱离了业务场景,其它开好人员根本不会用.因此,如果构造型查询的JPQL如果支持别名,这就太好了.我做了以下修改:

II.修改方案



1.修改[openjpa-kernel\src\main\jjtree\org\apache\openjpa\kernel\jpql\JPQL.jjt]


void constructor_parameter() #CONSTRUCTORPARAM : { }
{
 (path() | aggregate_select_expression() | string_literal() | numeric_literal()) [LOOKAHEAD(1)<AS>] [LOOKAHEAD(identification_variable())identification_variable()]
}


2.修改org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.java

private Expression assignProjections(JPQLNode parametersNode,
        QueryExpressions exps) 
{
        
int count = parametersNode.getChildCount();
        exps.projections 
= new Value[count];
        exps.projectionClauses 
= new String[count];
        exps.projectionAliases 
= new String[count];

        Expression exp 
= null;
        
        JPQLNode parentNode 
= null;
        JPQLNode itemNode 
= null;
        JPQLNode aliasNode 
= null;
        String alias 
= null;

        
for (int i = 0; i < count; i++{
          parentNode 
= parametersNode.getChild(i);
          itemNode 
= firstChild(parentNode);
          aliasNode 
= parentNode.children.length == 2 ? right(parentNode) : null;
          alias 
= aliasNode == null ? lastChild(itemNode).text : aliasNode.text;
          exps.projections[i] 
= getValue(itemNode);
          exps.projectionAliases[i] 
= alias == null ? nextAlias() : alias;
        }

        
return exp;
    }



3.用mvn重新编译打包,一切ok.

III.使用示例

场景:

/**
* A实体的一个DTO对象
*/

public class AData {
    
private String id;         //标识
    private String type;     //类型
    private String name;    //名称
    private int cnt;            //子的总数
    
}


@Entity
@Table(..)
private class A {
    @ID
    @GeneratedValue(generator 
= "uuid-hex")
    @Column(..)
    
private String id;
    @Column(..)
    
private String aName;
    @Column(..)
    
private String parentID;
    @OneToMany
    @Join..
    
private List<A> children;
    
}


JPQL语法如下:


select distinct new com.wile.test.AData(a.id, a.aName name, size(a.children) as cnt,'00' type) from A a where a.id=?1

虽然,我写的JPQL不太符合规范,但实在是太符合我的要求了.

posted on 2007-10-26 16:12 wilesun 阅读(1072) 评论(0)  编辑  收藏 所属分类: 个人经验

只有注册用户登录后才能发表评论。


网站导航: