На ваш вопрос нет простого ответа. Я сделал пару докладов об этом топи c. Иногда есть веские причины иметь и то, и другое в проекте.
Edit: IMHO Абстракция над базой данных в отношении диалектов и типов данных здесь не главное !! jOOQ отлично справляется с генерацией SQL для заданного целевого диалекта - и JPA / Hibernate тоже. Я бы даже сказал, что jOOQ делает все возможное, чтобы имитировать функции для баз данных, которые не имеют всех наворотов, таких как Postgres или Oracle. Здесь возникает вопрос: «Я хочу иметь возможность express запроса со всем, что может предложить SQL, или я доволен тем, что JPA может express?»
Вот пример совместной работы обоих. У меня есть репозиторий Spring Data JPA с настраиваемым расширением (необходимы интерфейс и реализация). Я позволяю контексту Spring вводить как JPA EntityManager
, так и контекст jOOQ. Затем я использую jOOQ для создания запросов и запуска их через JPA. Зачем? Потому что выразить рассматриваемый запрос с помощью JPA невозможно («Дайте мне то, что я слушал больше всего», который не имеет наибольшего количества подсчетов, но может быть несколько).
Причина, по которой я бегу запрос через JPA прост: нижестоящий вариант использования может потребовать от меня передать ему объекты JPA. jOOQ, конечно, может запускать этот запрос сам, и вы можете работать с записями или отображать данные в любом случае. Но поскольку вы конкретно спросили, возможно, использовать обе технологии, я подумал, что это хороший пример:
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.jooq.DSLContext;
import org.jooq.Field;
import org.jooq.Record;
import org.jooq.SelectQuery;
import org.jooq.conf.ParamType;
import org.jooq.impl.DSL;
import org.springframework.data.repository.CrudRepository;
import static ac.simons.bootiful_databases.db.tables.Genres.GENRES;
import static ac.simons.bootiful_databases.db.tables.Plays.PLAYS;
import static ac.simons.bootiful_databases.db.tables.Tracks.TRACKS;
import static org.jooq.impl.DSL.count;
import static org.jooq.impl.DSL.rank;
import static org.jooq.impl.DSL.select;
public interface GenreRepository extends
CrudRepository<GenreEntity, Integer>, GenreRepositoryExt {
List<GenreEntity> findAllByOrderByName();
}
interface GenreRepositoryExt {
List<GenreWithPlaycount> findAllWithPlaycount();
List<GenreEntity> findWithHighestPlaycount();
}
class GenreRepositoryImpl implements GenreRepositoryExt {
private final EntityManager entityManager;
private final DSLContext create;
public GenreRepositoryImpl(EntityManager entityManager, DSLContext create) {
this.entityManager = entityManager;
this.create = create;
}
@Override
public List<GenreWithPlaycount> findAllWithPlaycount() {
final Field<Integer> cnt = count().as("cnt");
return this.create
.select(GENRES.GENRE, cnt)
.from(PLAYS)
.join(TRACKS).onKey()
.join(GENRES).onKey()
.groupBy(GENRES.GENRE)
.orderBy(cnt)
.fetchInto(GenreWithPlaycount.class);
}
@Override
public List<GenreEntity> findWithHighestPlaycount() {
/*
select id, genre
from (
select g.id, g.genre, rank() over (order by count(*) desc) rnk
from plays p
join tracks t on p.track_id = t.id
join genres g on t.genre_id = g.id
group by g.id, g.genre
) src
where src.rnk = 1;
*/
final SelectQuery<Record> sqlGenerator =
this.create.select()
.from(
select(
GENRES.ID, GENRES.GENRE,
rank().over().orderBy(count().desc()).as("rnk")
).from(PLAYS)
.join(TRACKS).onKey()
.join(GENRES).onKey()
.groupBy(GENRES.ID, GENRES.GENRE)
).where(DSL.field("rnk").eq(1)).getQuery();
// Retrieve sql with named parameter
final String sql = sqlGenerator.getSQL(ParamType.NAMED);
// and create actual hibernate query
final Query query = this.entityManager.createNativeQuery(sql, GenreEntity.class);
// fill in parameter
sqlGenerator.getParams().forEach((n, v) -> query.setParameter(n, v.getValue()));
// execute query
return query.getResultList();
}
}
Я говорил об этом пару раз. В этих технологиях нет серебряной пули, иногда это очень тонкое суждение:
Полный текст здесь: https://speakerdeck.com/michaelsimons/live-with-your-sql-fetish-and-choose-the-right-tool-for-the-job
А также записанная версия это: https://www.youtube.com/watch?v=NJ9ZJstVL9E
Полный рабочий пример здесь https://github.com/michael-simons/bootiful-databases.