简体   繁体   English

[QueryDSL / Spring] java.lang.IllegalStateException:连接不是事务性的

[英][QueryDSL/Spring]java.lang.IllegalStateException: Connection is not transactional

I writing Spring+Vaadin application. 我编写Spring + Vaadin应用程序。 I wanted to add QueryDSL to access db (Oracle). 我想添加QueryDSL来访问数据库(Oracle)。 I looked in documentation ( http://docs.spring.io/spring-data/jdbc/docs/current/reference/html/core.querydsl.html ) and I read that Spring recommend using standard QueryDSL api. 我查看了文档( http://docs.spring.io/spring-data/jdbc/docs/current/reference/html/core.querydsl.html ),并阅读了Spring建议使用标准QueryDSL api的内容。 I improted to my project following dependecies: 我依赖于以下方面来介绍我的项目:

<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-sql-spring</artifactId>
    <version>${querydsl.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>com.mysema.querydsl</groupId>
    <artifactId>querydsl-sql</artifactId>
    <version>${querydsl.version}</version>
</dependency>

My beans.xml is as follows: 我的beans.xml如下:

<bean id="dataSourceOracle" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.oracle.driverClassName}" />
    <property name="url" value="${db.oracle.url}"/>
    <property name="username" value="${db.oracle.username}" />
    <property name="password" value="${db.oracle.password}" />
    <property name="defaultAutoCommit" value="false" />
</bean>

In my DatabaseFacade implementation I do following configuration: 在我的DatabaseFacade实现中,执行以下配置:

private SQLQueryFactory query;

@Autowired
@Qualifier("DataSource")
public void setDataSource(DataSource dataSource) {
    Provider<Connection> provider = new SpringConnectionProvider(dataSource);
    Configuration configuration = new Configuration(new OracleTemplates());
    configuration.setExceptionTranslator(new SpringExceptionTranslator());
    query = new SQLQueryFactory(configuration, provider);
}

Unfortunately everytime I start application I got: 不幸的是,每次我开始申请时,我都会得到:

10:29:54.490 [main] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
10:29:56.231 [main] ERROR c.r.i.k.b.impl.DatabaseFacadeImpl - Error happend in com.roche.icc.kps.backend.impl.DatabaseFacadeImpl.getEditableKPSStores
10:29:56.234 [main] ERROR c.r.i.k.b.impl.DatabaseFacadeImpl - Connection is not transactional
java.lang.IllegalStateException: Connection is not transactional
    at com.mysema.query.sql.spring.SpringConnectionProvider.get(SpringConnectionProvider.java:45) ~[querydsl-sql-spring-3.7.0.jar:na]
    at com.mysema.query.sql.spring.SpringConnectionProvider.get(SpringConnectionProvider.java:33) ~[querydsl-sql-spring-3.7.0.jar:na]
    at com.mysema.query.sql.SQLQueryFactory.query(SQLQueryFactory.java:63) ~[querydsl-sql-3.7.0.jar:na]
    at com.mysema.query.sql.SQLQueryFactory.query(SQLQueryFactory.java:28) ~[querydsl-sql-3.7.0.jar:na]
    at com.mysema.query.sql.AbstractSQLQueryFactory.from(AbstractSQLQueryFactory.java:54) ~[querydsl-sql-3.7.0.jar:na]

Did anyone encounter this problem? 有没有人遇到这个问题? Should I use different DataSource (Atomikos?)? 我应该使用其他DataSource (Atomikos吗?)?

Thanks for help! 感谢帮助!

Kamil 卡米尔

I came across with the same issue. 我遇到了同样的问题。

The issue is that QueryDSL expects the datasource connection to be in a transaction. 问题在于QueryDSL期望数据源连接处于事务中。 So either you have to explicitly begin transactions and handle it or the IOC container should do it for you. 因此,要么必须显式开始事务并进行处理,要么IOC容器应为您完成它。

In this case you most probably dont have the @Transactional annotation in any of your application layer (Service / Repository) which should have started a transaction. 在这种情况下,您很可能在应该启动事务的任何应用程序层(服务/存储库)中都没有@Transactional批注。

Add a @Transactional annotation to either your dao or service layer to fix the issue. 向您的dao或服务层添加@Transactional批注以解决此问题。

The links that helped me were https://groups.google.com/forum/#!topic/querydsl/_PqMek79TZE 对我有帮助的链接是https://groups.google.com/forum/#!topic/querydsl/_PqMek79TZE

An example project. 一个示例项目。 https://github.com/querydsl/querydsl/tree/master/querydsl-examples/querydsl-example-sql-spring https://github.com/querydsl/querydsl/tree/master/querydsl-examples/querydsl-example-sql-spring

Update 更新资料

This is how the DaoImpl from the example project. 这就是示例项目中的DaoImpl的方式。
Note the @Transactional annotation in the class level. 注意类级别的@Transactional批注。

@Transactional
public class CustomerDaoImpl implements CustomerDao {

@Inject
SQLQueryFactory queryFactory;

final QBean<CustomerAddress> customerAddressBean = bean(CustomerAddress.class,
        customerAddress.addressTypeCode, customerAddress.fromDate, customerAddress.toDate,
        bean(Address.class, address.all()).as("address"));

final QBean<Customer> customerBean = bean(Customer.class,
        customer.id, customer.name,
        bean(Person.class, person.all()).as("contactPerson"),
        GroupBy.set(customerAddressBean).as("addresses"));

@Override
public Customer findById(long id) {
    List<Customer> customers = findAll(customer.id.eq(id));
    return customers.isEmpty() ? null : customers.get(0);
}

@Override
public List<Customer> findAll(Predicate... where) {
    return queryFactory.from(customer)
        .leftJoin(customer.contactPersonFk, person)
        .leftJoin(customer._customer3Fk, customerAddress)
        .leftJoin(customerAddress.addressFk, address)
        .where(where)
        .transform(GroupBy.groupBy(customer.id).list(customerBean));
}

@Override
public Customer save(Customer c) {
    Long id = c.getId();

    if (id == null) {
        id = queryFactory.insert(customer)
                .set(customer.name, c.getName())
                .set(customer.contactPersonId, c.getContactPerson().getId())
                .executeWithKey(customer.id);
        c.setId(id);
    } else {
        queryFactory.update(customer)
            .set(customer.name, c.getName())
            .set(customer.contactPersonId, c.getContactPerson().getId())
            .where(customer.id.eq(c.getId()))
            .execute();

        // delete address rows
        queryFactory.delete(customerAddress)
            .where(customerAddress.customerId.eq(id))
            .execute();
    }

    SQLInsertClause insert = queryFactory.insert(customerAddress);
    for (CustomerAddress ca : c.getAddresses()) {
        if (ca.getAddress().getId() == null) {
            ca.getAddress().setId(queryFactory.insert(address)
                .populate(ca.getAddress())
                .executeWithKey(address.id));
        }
        insert.set(customerAddress.customerId, id)
            .set(customerAddress.addressId, ca.getAddress().getId())
            .set(customerAddress.addressTypeCode, ca.getAddressTypeCode())
            .set(customerAddress.fromDate, ca.getFromDate())
            .set(customerAddress.toDate, ca.getToDate())
            .addBatch();
    }
    insert.execute();

    c.setId(id);
    return c;
}

@Override
public long count() {
    return queryFactory.from(customer).fetchCount();
}

@Override
public void delete(Customer c) {
    // TODO use combined delete clause
    queryFactory.delete(customerAddress)
        .where(customerAddress.customerId.eq(c.getId()))
        .execute();

    queryFactory.delete(customer)
        .where(customer.id.eq(c.getId()))
        .execute();
}

}

In your case the annotation shall be placed in your DatabaseFacade Implementation. 对于您而言,注释应放在您的DatabaseFacade实现中。 I assume that your Spring application has a transaction manager configured as well. 我假设您的Spring应用程序也配置了事务管理器。

I encountered this issue and am able to fix this like below: 我遇到了这个问题,并能够像下面这样解决:

Besides that you should tag @Transactional annotation for your dao/Repository class, you also have to tag @EnableTransactionManagement for you spring java config class, just like below 除了应该为dao / Repository类标记@Transactional批注之外,还必须为spring java config类标记@EnableTransactionManagement ,如下所示

@Configuration
@EnableTransactionManagement
public class QuerydslConfiguration {
    @Bean
    public DataSource dataSource() {
        // implement your datasource
    }

    @Bean
    @Qualifier("transactionManager")
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public com.querydsl.sql.Configuration initConfiguration() {
        // check the spring integration section
    }

    @Bean
    public SQLQueryFactory queryFactory() {
        // check the spring integration section
    }
}

@Repository
@Transactional
public class PaymentDAO {
}

spring integration section 弹簧整合部

You can also state the EnableTransactionManagement in the spring context xml: 您还可以在spring上下文xml中声明EnableTransactionManagement
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.lang.IllegalStateException:没有可用的事务性 EntityManager - java.lang.IllegalStateException: No transactional EntityManager available Spring JPA测试java.lang.IllegalStateException - Spring JPA Test java.lang.IllegalStateException 春季启动 java.lang.IllegalStateException - Spring boot java.lang.IllegalStateException java.lang.IllegalStateException - java.lang.IllegalStateException Spring Data GemFire - 引起:java.lang.IllegalStateException:尚未创建连接池“DEFAULT” - Spring Data GemFire - Caused by: java.lang.IllegalStateException: The connection pool "DEFAULT" has not been created java.lang.IllegalStateException:来自 spring-integration-aws 库的连接池关闭异常 - java.lang.IllegalStateException: Connection pool shut down exception from spring-integration-aws library java.lang.IllegalStateException:连接池关闭于 - java.lang.IllegalStateException: Connection pool shut down at java.lang.IllegalStateException:连接池关闭异常 - java.lang.IllegalStateException: Connection pool shut down exception java.lang.IllegalStateException:连接池关闭 - java.lang.IllegalStateException: Connection pool shut down Weblogic和Spring JMS配置抛出java.lang.IllegalStateException - Weblogic and Spring JMS configuration throws java.lang.IllegalStateException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM