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

[QueryDSL/Spring]java.lang.IllegalStateException:连接不是事务性的,java,spring,querydsl,transactional,Java,Spring,Querydsl,Transactional,我正在编写Spring+Vaadin应用程序。我想将QueryDSL添加到access db(Oracle)中。我查阅了文档()并了解到Spring建议使用标准QueryDSLAPI。我在以下情况下加入了我的项目: <dependency> <groupId>com.mysema.querydsl</groupId> <artifactId>querydsl-sql-spring</artifactId> <

我正在编写Spring+Vaadin应用程序。我想将QueryDSL添加到access db(Oracle)中。我查阅了文档()并了解到Spring建议使用标准QueryDSLAPI。我在以下情况下加入了我的项目:

<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>
不幸的是,每次启动应用程序时,我都会得到:

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]
有人遇到过这个问题吗?我是否应该使用不同的
数据源
(Atomikos?)

谢谢你的帮助


卡米尔

我遇到了同样的问题

问题是QueryDSL希望数据源连接位于事务中。因此,要么您必须显式地开始事务并处理它,要么IOC容器应该为您完成

在这种情况下,您很可能在任何应用程序层(服务/存储库)中都没有@Transactional注释,而这些应用程序层本应启动事务

将@Transactional注释添加到dao或服务层以解决此问题

帮助我的链接是

一个范例项目

更新

这就是示例项目中DaoImpl的实现方式。
请注意类级别中的@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();
}

}
@Transactional
公共类CustomerDaoImpl实现CustomerDao{
@注入
SQLQueryFactory查询工厂;
最终QBean customerAddressBean=bean(CustomerAddress.class,
customerAddress.addressTypeCode、customerAddress.fromDate、customerAddress.toDate、,
bean(Address.class,Address.all()).as(“地址”);
最终QBean customerBean=bean(Customer.class,
customer.id,customer.name,
bean(Person.class,Person.all()).as(“contactPerson”),
set(customerAddressBean).as(“地址”);
@凌驾
公共客户findById(长id){
列出客户=findAll(customer.id.eq(id));
return customers.isEmpty()?null:customers.get(0);
}
@凌驾
公共列表findAll(谓词…where){
返回queryFactory.from(客户)
.leftJoin(customer.contactPersonFk,person)
.leftJoin(customer.\u customer3Fk,customerAddress)
.leftJoin(customerAddress.addressFk,地址)
.where(where)
.transform(GroupBy.GroupBy(customer.id).list(customerBean));
}
@凌驾
公共客户保存(客户c){
Long id=c.getId();
if(id==null){
id=queryFactory.insert(客户)
.set(customer.name,c.getName())
.set(customer.contactPersonId,c.getContactPerson().getId())
.executeWithKey(客户id);
c、 setId(id);
}否则{
queryFactory.update(客户)
.set(customer.name,c.getName())
.set(customer.contactPersonId,c.getContactPerson().getId())
.where(customer.id.eq(c.getId()))
.execute();
//删除地址行
queryFactory.delete(customerAddress)
.where(customerAddress.customerId.eq(id))
.execute();
}
SQLInsertClause insert=queryFactory.insert(customerAddress);
对于(CustomerAddress ca:c.getAddresses()){
if(ca.getAddress().getId()==null){
ca.getAddress().setId(queryFactory.insert(地址)
.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);
返回c;
}
@凌驾
公共长计数(){
返回queryFactory.from(customer.fetchCount();
}
@凌驾
公共作废删除(客户c){
//TODO使用组合删除子句
queryFactory.delete(customerAddress)
.where(customerAddress.customerId.eq(c.getId()))
.execute();
queryFactory.delete(客户)
.where(customer.id.eq(c.getId()))
.execute();
}
}

在您的情况下,注释应该放在DatabaseFacade实现中。我假设您的Spring应用程序也配置了事务管理器。

我遇到了这个问题,并且能够像下面这样解决这个问题:

除了应该为dao/Repository类标记
@Transactional
注释外,还必须为spring java配置类标记
@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上下文xml:

虽然此链接可以回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,仅链接的答案可能无效。-更新了答案以包含链接中的重要部分。
@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();
}

}
@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 {
}