在這,多次提到使用構(gòu)造型查詢,主要是我不想取出結(jié)果后再轉(zhuǎn)型,這樣,自己也實在太累了,因此,非常希望讓openJPA一下就將結(jié)果做好,畢竟感覺上性能也要好過使用簡單查詢方式。
I.openJPA的構(gòu)造型查詢
openJPA在構(gòu)造型查詢方面好過其它幾家,它支持三種方式:
1.通過反射注入,通過setXXX(字段名)注入到目標(biāo)類(dto對象)的字段中
2.通過put方法,目標(biāo)類(dto對象)需實現(xiàn)public void put(Object field, Object value)接口方法,然后openJPA的結(jié)果包裝器調(diào)用此接口,將數(shù)據(jù)寫到對象中
3.通過構(gòu)造方法,目標(biāo)類(dto對象)提供所需的構(gòu)造函數(shù),然后openJPA的結(jié)果包裝器通過該構(gòu)造函數(shù)實例化.
第1種方式最好,第3種方式最差,特別是對于查詢結(jié)果比較多,做構(gòu)造函數(shù)簡直就是不可能的事
用第1種方式,雖然最好,但在openJPA0.9.6,0.9.7及1.0.0中對于使用JPQL這種方式均受到限制,缺省情況下openJPA提供的字段名是jpqlalias1,..,而你的DTO對象不可能定義為jpqlalias1,,這樣的字段,這樣就脫離了業(yè)務(wù)場景,其它開好人員根本不會用.因此,如果構(gòu)造型查詢的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; //標(biāo)識
private String type; //類型
private String name; //名稱
private int cnt; //子的總數(shù)

}

@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不太符合規(guī)范,但實在是太符合我的要求了.