Java 如何在没有域类的querydsl中构造查询

Java 如何在没有域类的querydsl中构造查询,java,sql,jooq,querydsl,database-agnostic,Java,Sql,Jooq,Querydsl,Database Agnostic,在寻找java库以与数据库无关的方式构建查询时,我遇到了许多库,包括ICQL、querydsl、jooq、joist、hibernate等 我想要的东西不需要配置文件,可以使用动态模式。 对于我的应用程序,我在运行时了解了数据库和模式,因此不会有任何模式的配置文件或域类 这似乎是querydsl的核心目标之一,但在阅读querydsl的文档时,我看到了许多使用域类构建动态查询的示例,但我没有遇到任何东西解释如何仅使用我关于模式的动态信息构建这样的数据库不可知查询 Jooq提供了这样的功能(请参阅

在寻找java库以与数据库无关的方式构建查询时,我遇到了许多库,包括ICQL、querydsl、jooq、joist、hibernate等

我想要的东西不需要配置文件,可以使用动态模式。 对于我的应用程序,我在运行时了解了数据库和模式,因此不会有任何模式的配置文件或域类

这似乎是querydsl的核心目标之一,但在阅读querydsl的文档时,我看到了许多使用域类构建动态查询的示例,但我没有遇到任何东西解释如何仅使用我关于模式的动态信息构建这样的数据库不可知查询

Jooq提供了这样的功能(请参阅:),但如果我想将我的重点扩展到Oracle或MS SQL(我可能不喜欢但需要支持),则有一个限制性许可证

有querydsl经验的人能告诉我querydsl是否可以实现这种功能,如果可以,如何实现


如果有人知道任何其他可以满足我的要求的方法,我们将不胜感激。

更新:Timo向我展示了如何在不替换SQLQuery类的情况下执行我想要的操作,从而使我的原始响应无效。以下是他的评论:

query.getSQL(field1, field2, ... fieldN), getSQL is consistent with the
other methods which also take the projection arguments at last
我已经取消了不必要的课程。下面是一个使用SQLQuery直接获取SQL字符串而不执行查询的示例(例如,不使用
list
方法):


此响应回答了如何使用QueryDSL构建完整的SQL查询,而无需实际执行查询。它没有满足您关于“动态模式”和“没有域对象”的其他要求。…

一个非常简单的SQL查询,例如:

@Transactional
public User findById(Long id) {
    return new SQLQuery(getConnection(), getConfiguration())
      .from(user)
      .where(user.id.eq(id))
      .singleResult(user);
}
…可以这样动态创建(不添加任何糖):

@Transactional
公共用户findById(长id){
Path userPath=new-PathImpl(Object.class,“user”);
NumberPath idPath=Expressions.NumberPath(Long.class,userPath,“id”);
StringPath usernamePath=Expressions.StringPath(userPath,“username”);
Tuple Tuple=newsqlquery(getConnection(),getConfiguration())
.from(用户路径)
.其中(idPath.eq(id))
.singleResult(idPath、usernamePath);
返回新用户(tuple.get(idPath),tuple.get(usernamePath));
}

这里是ponzao使用PathBuilder解决方案的一个小变化

@Transactional
public User findById(Long id) {        
    PathBuilder<Object> userPath = new PathBuilder<Object>(Object.class, "user");
    NumberPath<Long> idPath = userPath.getNumber("id", Long.class);
    StringPath usernamePath = userPath.getString("username");
    Tuple tuple = new SQLQuery(getConnection(), getConfiguration())
      .from(userPath)
      .where(idPath.eq(id))
      .singleResult(idPath, usernamePath);
    return new User(tuple.get(idPath), tuple.get(usernamePath));
}
@Transactional
公共用户findById(长id){
PathBuilder userPath=新的PathBuilder(Object.class,“用户”);
NumberPath idPath=userPath.getNumber(“id”,Long.class);
StringPath usernamePath=userPath.getString(“用户名”);
Tuple Tuple=newsqlquery(getConnection(),getConfiguration())
.from(用户路径)
.其中(idPath.eq(id))
.singleResult(idPath、usernamePath);
返回新用户(tuple.get(idPath),tuple.get(usernamePath));
}

jOOQ用户在使用您描述的用例时过度使用了jOOQ,因此这是一个受良好支持的场景。感谢Lukas。我知道jOOQ支持这一点。我正在尝试看看querydsl是否可以做到这一点,因为它似乎拥有所需的主干网,而jOOQ需要许可才能添加对Oracle、MS SQL和Sybase等主要商业数据库的支持,而我无法做到这一点。感谢您的回复。虽然这确实解释了查询的构建,但它确实需要创建域类,因此不能像我的用例所要求的那样使用动态模式。@david fleeman您可以通过@TimoWestkämper方法直接获取SQL字符串和绑定-是的,如果您查看代码,我在回答中也会说明这一点。问题在于
select field1,field2
查询的一部分不是字符串的一部分,直到您实际调用执行查询的
list()
方法。如果您希望在不执行的情况下获得完整的SQL,那么据我所知,您需要我的helper类。如果我错了,请纠正我!像这样使用:query.getSQL(field1,field2,…fieldN),getSQL与其他方法是一致的,这些方法最后也接受了投影参数。@TimoWestkämper-ha,不知道我怎么会错过它。谢谢蒂莫!将把你的评论纳入我的答案中,让未来的读者看到如何正确地做。看起来很有希望。我会尝试,并以成功或失败作为回应。谢谢,谢谢。这太完美了。@MickJ,没问题!这实际上是一种非常有趣(也是罕见的?)的使用Querydsl的方法,我们很想听听它的效果如何。我在这里创建了它:如果能得到您的意见就太好了。基本上,我没有得到schema.table符号和所有参数显示为“?”而不是在查询中完全具体化。
@Transactional
public User findById(Long id) {
    Path<Object> userPath = new PathImpl<Object>(Object.class, "user");
    NumberPath<Long> idPath = Expressions.numberPath(Long.class, userPath, "id");
    StringPath usernamePath = Expressions.stringPath(userPath, "username");
    Tuple tuple = new SQLQuery(getConnection(), getConfiguration())
      .from(userPath)
      .where(idPath.eq(id))
      .singleResult(idPath, usernamePath);
    return new User(tuple.get(idPath), tuple.get(usernamePath));
}
@Transactional
public User findById(Long id) {        
    PathBuilder<Object> userPath = new PathBuilder<Object>(Object.class, "user");
    NumberPath<Long> idPath = userPath.getNumber("id", Long.class);
    StringPath usernamePath = userPath.getString("username");
    Tuple tuple = new SQLQuery(getConnection(), getConfiguration())
      .from(userPath)
      .where(idPath.eq(id))
      .singleResult(idPath, usernamePath);
    return new User(tuple.get(idPath), tuple.get(usernamePath));
}