Почему Querydsl всегда требует, чтобы соединение было транзакционным? - PullRequest
1 голос
/ 24 июня 2019

Недавно я попробовал новый инструмент для доступа к базе данных Querydsl в моем приложении Spring Boot, вот как я настраиваю контекст в @Configuration классе:

@Bean
public com.querydsl.sql.Configuration querydslConfiguration() {
    SQLTemplates templates = OracleTemplates.builder().build();
    com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);
    configuration.setExceptionTranslator(new SpringExceptionTranslator());
    return configuration;
}

@Bean
public SQLQueryFactory queryFactory(DataSource dataSource) {
    Provider<Connection> provider = new SpringConnectionProvider(dataSource);
    return new SQLQueryFactory(querydslConfiguration(), provider);
}

Мой запрос довольно прост:

fun detailedEntityByIds(ids: Set<String>): List<DetailedEntity> {
    val qDetails = QTContainerDetails.tContainerDetails
    return sqlQueryFactory.select(qDetails).from(qDetails)
        .where(qDetails.id.`in`(ids))
        .fetch().map { mapper.qDslEntToModel(it) }
}

Тогда я столкнулся со следующим исключением:

java.lang.IllegalStateException: соединение не является транзакционным

Я быстро нашел этот вопрос: [QueryDSL / Spring] java.lang.IllegalStateException: Соединение не является транзакционным с рекомендацией использовать @Transactional для решения этой проблемы.

Почему Querydsl требует, чтобы соединения были транзакционными? Раньше я ставил @Transactional на методы уровня сервиса, где он мне действительно нужен. Теперь Querydsl «заставляет» меня поместить его в целый класс DAO, потому что похоже, что это требуется для каждого запроса Querydsl.

1 Ответ

1 голос
/ 03 июля 2019

Из Javadoc

<code>/**
 * {@code SpringConnectionProvider} is a Provider implementation which provides a transactionally bound connection
 *
 * <p>Usage example</p>
 * <pre>
 * {@code
 * Provider<Connection> provider = new SpringConnectionProvider(dataSource());
 * SQLQueryFactory queryFactory = SQLQueryFactory(configuration, provider);
 * }
 * 
* /

Причина в управлении ресурсами. У вас нет доступа к базовой реализации JDBC. Транзакция закроет ResultSets, Statements, Connections и т. Д. Без транзакции каждое соединение останется открытым, пул соединений будет заполнен, база данных исчерпает ресурсы и т. Д.

Если вы хотите управлять своими собственными ресурсами, вы можете написать свой собственный Provider<Connection> и передать DataSource E.G.

private static Provider<Connection> getConnection(DataSource dataSource) {
    return () -> org.springframework.jdbc.datasource.DataSourceUtils.getConnection(dataSource);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...