org.jooq.exception.DetachedException:无法执行查询。未配置连接

时间:2019-08-02 11:49:33

标签: junit h2 jooq

我有jOOQ(3.11.11)+ H2 + Spring应用程序,其中我试图运行一个简单的JUnit测试以实现持久性,但是没有例外。

这是我的application.properties文件:

spring.datasource.url=jdbc:h2:mem:jooq-test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL
spring.datasource.platform=h2
spring.datasource.username = sa
spring.datasource.password =

我的测试配置类为:

@Configuration
public class DummyTestConfig {
    @Bean
    public DSLContext dsl() {
        return DSL.using(SQLDialect.H2);
    }
}

还有我的测试用例:

public class JooqRepositoryImplTest {

    @MockBean
    private PlatformCache platformCache;

    @Autowired
    private JooqRepositoryImpl JooqRepository;

    private List<Entity> getDummyEntityList() {
        List<Entity> data = new ArrayList<>();
        for (int i = 0; i < 15; i++) {
            data.add(getDummyEntity());
        }
        return data;
    }

    private Entity getDummyEntity() {
        final Entity entity = new Entity();
        entity.setCapacity(150);
        return entity;
    }

    @Test
    public void testDatabaseIsUp() {
        assert(1 == JooqRepository.count());
    }

    @Test
    public void testReplace() {
        JooqRepository.getEntitiesByJDBC(124, "C", DirectionEnum.I, TrafficBucketEnum.D);
    }

    @Test
    public void testSave() {
        final List<Entity> data = getDummyEntityList();
        JooqRepository.batchSaveByJDBC(data);
    }
}

我的存储库实现

@Repository
public class JooqRepositoryImpl implements CustomRepository {

    @Autowired
    private DSLContext dslContext;

    public int count() {
        return dslContext.fetchCount(MyTable.MY_TABLE);
    }

    @Transactional
    @Override
    public void batchSaveByJDBC(List<Entity> entities) {
        dslContext.batchInsert(entities.parallelStream().map(convertEntityToRecord()).collect(Collectors.toList()));
    }

    private Function<Entity, Record> convertEntityToRecord() {
        return entity ->  {
            final Record record = new Record();
            record.setCapacity(entity.getCapacity());
            return record;
        };
    }

    @Override
    public void batchReplaceByJDBC(List<Entity> entities) {
        executeReplace(MyTable.MY_TABLE, entities.toArray());
    }

    public int executeReplace(Table<Record> table, Object[] values) {
        return dslContext.execute("replace into {0} ({1}) values ({2})",
                table,
                dslContext.informationSchema(table).getColumns(),
                DSL.list(Stream.of(values).map(DSL::val).collect(Collectors.toList()))
        );
    }

    @Override
    public void batchUpdateByJDBC(List<Entity> entities,
                                  LegRoutingTO leg) {
        dslContext.batchUpdate(entities.parallelStream().map(convertEntityToRecord()).collect(Collectors.toList()));
    }

    @Override
    public void batchUpdateByJDBCPartial (
            List<Entity> entities, LegRoutingTO leg) {
        final Batch updates = dslContext.batch(
                entities.parallelStream().map(convertEntityToRecord()).map(convertRecordToQuery()).collect(Collectors.toList()));
        updates.execute();
    }

    private Function<Record, Query> convertRecordToQuery() {
        return record -> {
            final UpdateQuery<Record> query = dslContext.updateQuery(MyTable.MY_TABLE);
            query.setRecord(record);
            return query;
        };
    }

    private Function<Record, Entity> convertRecordToEntity() {
        return record -> {
            final Entity entity = new Entity();
            BeanUtils.copyProperties(record, entity);
            return entity;
        };
    }

}

编辑:我的pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jooq</artifactId>
        </dependency>
    </dependencies>

<build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>sql-maven-plugin</artifactId>
                <version>1.5</version>

                <!-- Skip DB creation if the value of the skip.db.creation property is 
                    true -->
                <configuration>
                    <skip>${skip.db.creation}</skip>
                </configuration>

                <executions>
                    <!-- Execute SQL statements to the configured database -->
                    <execution>
                        <id>create-database-h2</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>execute</goal>
                        </goals>
                        <configuration>
                            <!-- Configure the database connection -->
                            <driver>org.h2.Driver</driver>
                            <url>jdbc:h2:~/sampledb;INIT=CREATE SCHEMA IF NOT EXISTS
                                sampledb</url>
                            <username>sa</username>
                            <password></password>

                            <!-- Ensure that our changes are committed automatically -->
                            <autocommit>true</autocommit>
                            <!-- Configure the location of the invoked SQL script -->
                            <srcFiles>
                                <srcFile>src/main/resources/schema.sql</srcFile>
                            </srcFiles>
                        </configuration>
                    </execution>
                </executions>

                <dependencies>
                    <!-- Because we use the H2 database, we have to add it as the dependency 
                        of this plugin. -->
                    <dependency>
                        <groupId>com.h2database</groupId>
                        <artifactId>h2</artifactId>
                        <version>${com.h2database.version}</version>
                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.jooq</groupId>
                <artifactId>jooq-codegen-maven</artifactId>
                <version>3.4.4</version>

                <executions>
                    <!-- Generate the required class from the database -->
                    <execution>
                        <id>generate-h2</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>

                <dependencies>
                    <!-- Because we use the H2 database, we have to add it as the dependency 
                        of this plugin. -->
                    <dependency>
                        <groupId>com.h2database</groupId>
                        <artifactId>h2</artifactId>
                        <version>${com.h2database.version}</version>
                    </dependency>
                </dependencies>

                <configuration>
                    <!-- Configure the database connection -->
                    <jdbc>
                        <driver>org.h2.Driver</driver>
                        <url>jdbc:h2:~/sampledb;INIT=CREATE SCHEMA IF NOT EXISTS
                            FORECAST_MEASURES</url>
                        <user>sa</user>
                        <password></password>
                    </jdbc>

                    <generator>
                        <database>
                            <!-- Configure the used database dialect -->
                            <name>org.jooq.util.h2.H2Database</name>
                            <!-- Include all tables found from the PUBLIC schema -->
                            <includes>.*</includes>
                            <excludes></excludes>
                            <inputSchema>PUBLIC</inputSchema>
                        </database>
                        <!-- Generate classes for tables and records -->
                        <generate>
                            <records>true</records>
                        </generate>
                        <!-- Configure the target package and dirmectory -->
                        <target>
                            <packageName>com.xxxx.entity.jooq</packageName>
                            <directory>src/main/java</directory>
                        </target>
                    </generator>
                </configuration>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings 
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>
                                            org.codehaus.mojo
                                        </groupId>
                                        <artifactId>
                                            sql-maven-plugin
                                        </artifactId>
                                        <versionRange>
                                            [1.5,)
                                        </versionRange>
                                        <goals>
                                            <goal>execute</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>


----------


当我尝试运行测试用例时,其中一个通过(testBatchInsert),而另外两个则失败,并带有以下堆栈跟踪:


org.jooq.exception.DetachedException: Cannot execute query. No Connection configured

    at org.jooq_3.11.11.H2.debug(Unknown Source)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:319)
    at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:393)
    at org.jooq.impl.AbstractResultQuery.fetchLazy(AbstractResultQuery.java:380)
    at org.jooq.impl.AbstractResultQuery.fetchStream(AbstractResultQuery.java:351)
    at org.jooq.impl.SelectImpl.fetchStream(SelectImpl.java:2716)
    at com.xxxx.repository.implementation.JooqRepositoryImpl.getEntitiesByJDBC(JooqRepositoryImpl.java:159)
    at com.xxxx.repository.implementation.JooqRepositoryImpl$$FastClassBySpringCGLIB$$8ff9f08.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
    at com.xxxx.repository.implementation.JooqRepositoryImpl$$EnhancerBySpringCGLIB$$923a185d.getEntitiesByJDBC(<generated>)
    at com.xxxx.repository.implementation.JooqRepositoryImplTest.testReplace(JooqRepositoryImplTest.java:126)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:66)

1 个答案:

答案 0 :(得分:0)

原因是您的DSLContext配置:

@Configuration
public class DummyTestConfig {
    @Bean
    public DSLContext dsl() {
        return DSL.using(SQLDialect.H2);
    }
}

它未连接到您的数据源。要么,您需要将数据源注入此配置,然后使用它:

@Configuration
public class DummyTestConfig {
    @Autowired
    DataSource ds;

    @Bean
    public DSLContext dsl() {
        return DSL.using(ds, SQLDialect.H2);
    }
}

或者您根本不执行此操作,而是使用Spring Boot注入的DSLContext。将此添加到您的application.properties文件中:

#jOOQ Configuration
spring.jooq.sql-dialect=H2

您可以在此处找到示例项目:https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-spring-boot-example