论坛首页 Java企业应用论坛

QueryDSL学习笔记

浏览 22470 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (1)
作者 正文
   发表时间:2012-03-23   最后修改:2012-03-23

最近部门同事在开发统一数据服务层,了解到其底层使用到了QueryDSL,于是花了几个小时在网上看了一下资料,写了一个小例子,供大家参考;

QueryDSL介绍

  • QueryDSL仅仅是一个通用的查询框架,专注于通过Java API构建类型安全的SQL查询。
  • Querydsl可以通过一组通用的查询API为用户构建出适合不同类型ORM框架或者是SQL的查询语句,也就是说QueryDSL是基于各种ORM框架以及SQL之上的一个通用的查询框架。
  • 借助QueryDSL可以在任何支持的ORM框架或者SQL平台上以一种通用的API方式来构建查询。目前QueryDSL支持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,Hibernate Search。

 

不多介绍了,有兴趣的可以直接上官网:http://www.querydsl.com/

示例代码

1、根据数据库schema,创建QModel:

/**
 * QMember is a Querydsl query type for QMember
 */
@Schema("PUBLIC")
@Table("MEMBER")
public class QMember extends RelationalPathBase<QMember> {

    private static final long        serialVersionUID = 448912875;

    public static final QMember      member           = new QMember("MEMBER");

    public final StringPath          address          = createString("ADDRESS");

    public final StringPath          city             = createString("CITY");

    public final StringPath          country          = createString("COUNTRY");

    public final StringPath          email            = createString("EMAIL");

    public final StringPath          firstName        = createString("FIRST_NAME");

    public final StringPath          lastName         = createString("LAST_NAME");

    public final StringPath          memberId         = createString("MEMBER_ID");

    public final StringPath          password         = createString("PASSWORD");

    public final StringPath          phone            = createString("PHONE");

    public final PrimaryKey<QMember> memberPk         = createPrimaryKey(memberId);

    public QMember(String variable){
        super(QMember.class, forVariable(variable));
    }

    public QMember(BeanPath<? extends QMember> entity){
        super(entity.getType(), entity.getMetadata());
    }

    public QMember(PathMetadata<?> metadata){
        super(QMember.class, metadata);
    }

}
 

2、根据生成出来的QModel来查询数据:

private static void queryFromDsl(Connection conn) {
	QMember qm = QMember.member;

	SQLTemplates dialect = new HSQLDBTemplates();
	SQLQuery query = new SQLQueryImpl(conn, dialect);
	List<String> lastNames = query.from(qm).list(qm.lastName);
	// select last_name from member
	System.out.println(lastNames);

	SQLQuery query2 = new SQLQueryImpl(conn, dialect);
	System.out.println(query2.from(qm).count());
	// select count(*) from member

	SQLQuery query3 = new SQLQueryImpl(conn, dialect);
	List<Object[]> results = query3.from(qm).orderBy(qm.lastName.desc()).list(qm.firstName, qm.lastName);
	for (Object[] o : results) {
		System.out.println(ToStringBuilder.reflectionToString(o, ToStringStyle.SIMPLE_STYLE));
	}
	// select first_name, last_name from member order by last_name desc

	SQLQuery query4 = new SQLQueryImpl(conn, dialect);
	List<Object[]> members = query4.from(qm).where(qm.lastName.like("last%")).list(qm.all());
	for (Object[] o : members) {
		System.out.println(ToStringBuilder.reflectionToString(o, ToStringStyle.SIMPLE_STYLE));
	}
	// select * from member where last_name like 'last%'
}
 

注意到上面注释的部分,分别对应的是相应查询代码的SQL语句,流式查询语句写起来很爽啊!

更多要做的事情

目前只是写了个很简单的例子,体会了一下它的功能,要大范围使用,需要更深入的研究一下;

 

另外,可能大家已经想到:

  • QueryDSL只是通用的查询框架,不支持写操作
  • 查询出来的结果是List,我们不得不做额外的工作将它转化为领域实体

以上两点也正是统一数据服务层要解决的问题!

 

有兴趣的同学,可以下载附件示例代码!

   发表时间:2012-03-23  
QueryDSL也是支持写操作的,详见:
DMLClause
<--DeleteClause
<--StoreClause
      <-- InsertClause
      <-- UpdateClause

而QueryDsl-JPA实现中,是支持Model的转换的。

SpringData底层也是依赖QueryDSL的。
0 请登录后投票
   发表时间:2012-03-23  
stone2083 写道
QueryDSL也是支持写操作的,详见:
DMLClause
<--DeleteClause
<--StoreClause
      <-- InsertClause
      <-- UpdateClause

而QueryDsl-JPA实现中,是支持Model的转换的。

SpringData底层也是依赖QueryDSL的。


好的,感谢stone2083的提醒,我再仔细看看。
0 请登录后投票
   发表时间:2012-03-25  
这玩意看过,不过觉得不怎么好,要自己生成很多代理查询的类!!!
0 请登录后投票
   发表时间:2012-03-25  
跟mybatis比起来,有啥优势?
跟hibernate比,就更加没优势了
0 请登录后投票
   发表时间:2012-03-25  
KimHo 写道
跟mybatis比起来,有啥优势?
跟hibernate比,就更加没优势了

QueryDSL, 在Hibernate,mybatis之上,构建的一套api.. 只处理查询操作和常用ORM没什么冲突。

优势如下:
引用

Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API.

Code completion in IDE (all properties, methods and operations can be expanded in your favorite Java IDE)
Almost no syntactically invalid queries allowed (type-safe on all levels)
Domain types and properties can be referenced safely (no Strings involved!)
Adopts better to refactoring changes in domain types
Incremental query definition is easier


0 请登录后投票
   发表时间:2012-03-26  
链式编程的风格不容易维护,令人讨厌!
0 请登录后投票
   发表时间:2012-03-26  
wenshao 写道
链式编程的风格不容易维护,令人讨厌!

链式编程的风格为什么讨厌呢?连jQuery也是采用这样的方式。
0 请登录后投票
   发表时间:2012-03-26  
llade 写道
wenshao 写道
链式编程的风格不容易维护,令人讨厌!

链式编程的风格为什么讨厌呢?连jQuery也是采用这样的方式。

也看个人吧,querydsl的流式编程,相比SQL语句不那么直观。任何事情都是一种取舍,看偏重哪一面了!
0 请登录后投票
   发表时间:2012-03-26  
diecui1202 写道
llade 写道
wenshao 写道
链式编程的风格不容易维护,令人讨厌!

链式编程的风格为什么讨厌呢?连jQuery也是采用这样的方式。

也看个人吧,querydsl的流式编程,相比SQL语句不那么直观。任何事情都是一种取舍,看偏重哪一面了!


引用

Almost no syntactically invalid queries allowed (type-safe on all levels)
Domain types and properties can be referenced safely (no Strings involved!)
Adopts better to refactoring changes in domain types
Incremental query definition is easier


这4点可以明显的减少调试、开发、单元测试等的难度和时间。
如果不值得取舍的话,还真无话可说。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics