Search code examples
javasqljooqquerydsldatabase-agnostic

How to construct query in querydsl without domain classes


While looking for java libraries to build queries in a database agnostic way I came across many including iciql, querydsl, jooq, joist, hibernate etc.

I wanted something that does not require configuration files and can work with dynamic schemas. For my application, I come to know about the database and the schema at runtime so I won't have any configuration files or domain classes for the schema.

This seems to be one of the core goals of querydsl but going through the documentation for querydsl I see a lot of examples for building dynamic queries using domain classes but I have not come across anything that explains how to build such database agnostic queries using just the dynamic information I have about the schema.

Jooq offers such functionality(See: http://www.jooq.org/doc/3.2/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/) but have a restrictive license if I want to expand my focus to Oracle or MS SQL(Which I may not love but need to support).

Can someone with experience in querydsl let me know if such a thing is possible with querydsl, and if yes, how.

If someone know of any other too which can satisfy my requirements, it would be really appreciated.


Solution

  • A very simple SQL query such as this:

    @Transactional
    public User findById(Long id) {
        return new SQLQuery(getConnection(), getConfiguration())
          .from(user)
          .where(user.id.eq(id))
          .singleResult(user);
    }
    

    ...can be created dynamically like this (without any sugar added):

    @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));
    }