在 jooq 中使用 DAO 时出现 DataAccessException

Posted

技术标签:

【中文标题】在 jooq 中使用 DAO 时出现 DataAccessException【英文标题】:DataAccessException when using DAO in jooq 【发布时间】:2020-02-21 06:41:11 【问题描述】:

我想使用 DAO 将 Generated Pojo 添加到数据库中。 但是我收到一个异常并且不知道如何解决它。

我尝试在每个 Table 前面添加一个 Public.Troop。

将部队插入 DAO 用法:

TroopDao dao = new TroopDao(new DefaultConfiguration().set(SQLDialect.SQLITE).set(database.getConnection()));
Troop initial = new Troop(1, 100, 120, 120.2, 11.2, 12.0, 13.0, 6245.0, 1534.0, 1364.0, 121235.3, 125.3, 51.3);
dao.insert(initial);

使用的数据库文件:

CREATE TABLE IF NOT EXISTS TROOP(
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    current_health INTEGER NOT NULL,
    max_health INTEGER NOT NULL,
    pos_x DOUBLE NOT NULL,
    pos_y DOUBLE NOT NULL,
    normal_speed DOUBLE NOT NULL,
    street_speed DOUBLE NOT NULL,
    difficult_terrain_speed DOUBLE NOT NULL,
    close_combat_range DOUBLE NOT NULL,
    ranged_combat_range DOUBLE NOT NULL,
    normal_view_distance DOUBLE NOT NULL,
    disadvantaged_view_distance DOUBLE NOT NULL,
    advantaged_view_distance DOUBLE NOT NULL
);

CREATE TABLE IF NOT EXISTS ARMY(
    id INTEGER,
    hq INTEGER,
    troop INTEGER,
    FOREIGN KEY(hq) REFERENCES TROOP(id),
    FOREIGN KEY(troop) REFERENCES TROOP(id),
    UNIQUE(hq, troop),
    PRIMARY KEY (id, hq, troop)
);

JOOQ 生成,我也试过 unqualifiedSchema = main:

        Configuration configuration = new Configuration()
                .withGenerator(new Generator()
                        .withDatabase(new Database()
                                .withName("org.jooq.meta.extensions.ddl.DDLDatabase")
                                .withIncludes("ARMY | TROOP")
                                .withOutputSchemaToDefault(Boolean.TRUE)
                                .withProperties(new Property()
                                                .withKey("unqualifiedSchema")
                                                .withValue("none"),
                                        new Property()
                                                .withKey("scripts")
                                                .withValue("/db/schema.sql")))
                        .withGenerate(new Generate()
                                .withPojos(Boolean.TRUE)
                                .withDeprecationOnUnknownTypes(Boolean.FALSE)
                                .withImmutableInterfaces(Boolean.TRUE)
                                .withDaos(Boolean.TRUE))
                        .withTarget(new Target()
                                .withPackageName("me.leslie.generals.server.persistence.jooq")
                                .withDirectory("Generals-Server/src/main/java")));

        GenerationTool.generate(configuration);

Databaseclass 只是一个返回基本 DataBaseconnection 的单例:

@EqualsAndHashCode
@ToString
@Getter
public class Database 
    public static final String DEFAULT_DB_URL = "jdbc:sqlite:";
    @NonNull
    private final String url;
    private final Connection connection;

    private static Database instance;

    public static Database get() 
        if(instance == null)
            instance = new Database(DEFAULT_DB_URL);
        
        return instance;
    

    private Database(String url) 
        try 
            this.connection = DriverManager.getConnection(url);
         catch (SQLException e) 
            throw new InitializationException("Could not get Database connection", e);
        
        initialize();
        this.url = url;
    


    private void initialize() 
        final String troopSchema = "CREATE TABLE IF NOT EXISTS TROOP(" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "current_health INTEGER NOT NULL," +
                "max_health INTEGER NOT NULL," +
                "pos_x DOUBLE NOT NULL," +
                "pos_y DOUBLE NOT NULL," +
                "normal_speed DOUBLE NOT NULL," +
                "street_speed DOUBLE NOT NULL," +
                "difficult_terrain_speed DOUBLE NOT NULL," +
                "close_combat_range DOUBLE NOT NULL," +
                "ranged_combat_range DOUBLE NOT NULL," +
                "normal_view_distance DOUBLE NOT NULL," +
                "disadvantaged_view_distance DOUBLE NOT NULL," +
                "advantaged_view_distance DOUBLE NOT NULL" +
                ");";


        final String armySchema = "CREATE TABLE IF NOT EXISTS ARMY(" +
                "id INTEGER," +
                "hq INTEGER," +
                "troop INTEGER," +
                "FOREIGN KEY(hq) REFERENCES TROOP(id)," +
                "FOREIGN KEY(troop) REFERENCES TROOP(id)," +
                "UNIQUE(hq, troop)," +
                "PRIMARY KEY (id, hq, troop)" +
                ");";

        try (PreparedStatement sql = connection.prepareStatement(troopSchema)) 
            sql.execute();


         catch (SQLException e) 
            throw new InitializationException("Could not initialize Troops", e);
        

        try (PreparedStatement sql = connection.prepareStatement(armySchema)) 
            sql.execute();
         catch (SQLException e) 
            throw new InitializationException("Could not initialize Armies", e);
        
    

错误,当我使用基于文件的数据库并访问它时,所需的表似乎在那里:

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.jooq.tools.reflect.Reflect (file:/home/leslie/.m2/repository/org/jooq/jooq/3.11.11/jooq-3.11.11.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class)
WARNING: Please consider reporting this to the maintainers of org.jooq.tools.reflect.Reflect
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
23:32:56.084 [main] INFO org.jooq.Constants - 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@  @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@
@@@@@@@@@@@@@@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@  @@@@  @@  @@    @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@    @@  @@  @@@@  @@@@@@@@@@
@@@@@@@@@@        @@  @  @  @@@@@@@@@@
@@@@@@@@@@        @@        @@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  Thank you for using jOOQ 3.11.11

23:32:56.093 [main] DEBUG org.jooq.tools.LoggerListener - Executing query          : select PUBLIC.TROOP.ID from PUBLIC.TROOP
23:32:56.099 [main] DEBUG org.jooq.tools.LoggerListener - Exception                
org.jooq.exception.DataAccessException: SQL [select PUBLIC.TROOP.ID from PUBLIC.TROOP]; [SQLITE_ERROR] SQL error or missing database (no such table: PUBLIC.TROOP)
    at org.jooq_3.11.11.SQLITE.debug(Unknown Source)
    at org.jooq.impl.Tools.translate(Tools.java:2430)
    at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:832)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:364)
    at org.jooq.impl.AbstractResultQuery.fetch(AbstractResultQuery.java:323)
    at org.jooq.impl.SelectImpl.fetch(SelectImpl.java:2700)
    at me.leslie.generals.server.repository.TroopJooqRepository.nextID(TroopJooqRepository.java:47)
    at me.leslie.generals.server.repository.TroopJooqRepository.create(TroopJooqRepository.java:60)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    at org.jooq.lambda.SeqImpl.collect(SeqImpl.java:190)
    at me.leslie.generals.server.repository.TroopJooqRepositoryTest.initializeTroops(TroopJooqRepositoryTest.java:38)
    at me.leslie.generals.server.repository.TroopJooqRepositoryTest.getSomeTroops(TroopJooqRepositoryTest.java:152)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:675)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:125)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:132)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:124)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:74)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:104)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:62)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:43)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:35)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:202)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:198)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1507)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    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)
Caused by: org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such table: PUBLIC.TROOP)
    at org.sqlite.core.DB.newSQLException(DB.java:941)
    at org.sqlite.core.DB.newSQLException(DB.java:953)
    at org.sqlite.core.DB.throwex(DB.java:918)
    at org.sqlite.core.NativeDB.prepare_utf8(Native Method)
    at org.sqlite.core.NativeDB.prepare(NativeDB.java:134)
    at org.sqlite.core.DB.prepare(DB.java:257)
    at org.sqlite.core.CorePreparedStatement.<init>(CorePreparedStatement.java:47)
    at org.sqlite.jdbc3.JDBC3PreparedStatement.<init>(JDBC3PreparedStatement.java:30)
    at org.sqlite.jdbc4.JDBC4PreparedStatement.<init>(JDBC4PreparedStatement.java:19)
    at org.sqlite.jdbc4.JDBC4Connection.prepareStatement(JDBC4Connection.java:35)
    at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:241)
    at org.sqlite.jdbc3.JDBC3Connection.prepareStatement(JDBC3Connection.java:205)
    at org.jooq.impl.ProviderEnabledConnection.prepareStatement(ProviderEnabledConnection.java:109)
    at org.jooq.impl.SettingsEnabledConnection.prepareStatement(SettingsEnabledConnection.java:73)
    at org.jooq.impl.AbstractResultQuery.prepare(AbstractResultQuery.java:239)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:322)
    ... 77 common frames omitted

【问题讨论】:

【参考方案1】:

根据 jOOQ 3.12,DDLDatabase 解析您的 SQL 脚本,将它们转换为 H2 并针对内存中的 H2 数据库运行它们,该数据库使用 PUBLIC 作为默认架构,您的所有表现在都位于代码生成器的观点。

这样的架构在 SQLite 中不存在,这就是为什么您会收到您所看到的错误。 jOOQ 3.12 通过支持新的unqualifiedSchema 属性解决了这个问题,该属性允许在 DDL 脚本中指定所有不合格表的隐含模式。默认情况下,假设这映射到 H2 中的 PUBLICPUBLIC 被假定为“默认模式”。因此,要解决此问题,只需升级到 jOOQ 3.12。在此处查看更多详细信息: https://www.jooq.org/doc/latest/manual/code-generation/codegen-ddl

注意:您已经在使用此标志,但您没有使用 jOOQ 3.12。 3.11.11 还没有。

【讨论】:

以上是关于在 jooq 中使用 DAO 时出现 DataAccessException的主要内容,如果未能解决你的问题,请参考以下文章

通过 JOOQ-meta 访问 H2 元模型时出现 SQLException

使用 jOOQ 和 Spring Boot 进行集成测试时出现“PSQLException: FATAL: sorry, too many clients already”错误

如何在使用 jooq 生成的 dao 插入/更新后获取插入/更新的对象

JOOQ DAO 使用事务支持

jOOQ 自定义 Pojo 和 DAO 生成

使用 FindFirst 时出现 DAO RecordSet 错误 3251