Как построить запрос в querydsl без доменных классов

При поиске библиотек Java для создания запросов без учета базы данных я сталкивался со многими, включая iciql, querydsl, jooq, joist, hibernate и т. Д.

Я хотел что-то, что не требует конфигурационных файлов и может работать с динамическими схемами. Для моего приложения я узнаю о базе данных и схеме во время выполнения, поэтому у меня не будет никаких файлов конфигурации или классов домена для схемы.

Кажется, это одна из основных целей querydsl, но, просматривая документацию по querydsl, я вижу много примеров построения динамических запросов с использованием классов домена, но я не встречал ничего, что объясняло бы, как создавать такие независимые от базы данных запросы, используя только У меня есть динамическая информация о схеме.

Jooq предлагает такую ​​функциональность (см.: http://www.jooq.org/doc/3.2/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder/), но если у вас есть ограничительная лицензия Я хочу расширить свое внимание на Oracle или MS SQL(который я, возможно, не люблю, но нуждаюсь в поддержке).

Может кто-то с опытом в querydsl, дайте мне знать, если такое возможно с querydsl, и если да, то как.

Если бы кто-то знал о любом другом, который может удовлетворить мои требования, это было бы очень ценно.

3 ответа

Решение

Очень простой запрос SQL, такой как этот:

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

... может быть создан динамически следующим образом (без добавления сахара):

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

Вот небольшой вариант решения Понзао с использованием 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));
}

Обновление: Тимо аннулировал мой первоначальный ответ, показав мне, как делать то, что я хочу, БЕЗ замены класса SQLQuery. Вот его комментарий:

query.getSQL(field1, field2, ... fieldN), getSQL is consistent with the
other methods which also take the projection arguments at last

Я удалил свой ненужный класс. Вот пример использования SQLQuery напрямую для получения строки SQL БЕЗ выполнения запроса (например, без использования list метод):

SQLQuery rquery = new SQLQuery(connection , dialect);

// Use getSQL with projections
rquery.from(qtable)
    .where(qtable.qfield1.eq("somevalue"));

SQLBindings bindings = rquery.getSQL(qtable.qfield1, qtable.qfield2);

// Get the SQL string from the SQLBindings
System.out.println(bindings.getSql());

// Get the SQL parameters from the SQLBindings for the parameterized query
System.out.println(bindings.getBindings());

Этот ответ дает ответ о том, как использовать QueryDSL для построения полного запроса SQL без фактического его выполнения. Он не отвечает вашим дополнительным требованиям о "динамических схемах" и "без доменных объектов"...

Другие вопросы по тегам