使用 Spring Boot 进行 JOOQ SQL 语法转换

Posted

技术标签:

【中文标题】使用 Spring Boot 进行 JOOQ SQL 语法转换【英文标题】:JOOQ SQL Syntax conversion with Spring Boot 【发布时间】:2021-01-04 01:30:40 【问题描述】:

我有一个 SQL CE 语法的 SQL 脚本导出。当我的应用程序启动时,jooq 应该读取此脚本,将其解析为与 h2 兼容的 sql,然后将 create 和 insert 语句读取到我的 h2 db 中。不幸的是,我似乎无法让 JOOQ 在 Spring Boot 下运行。

我阅读了一些教程,但到目前为止,我最好阅读 Baeldung 的 Spring Boot 教程。但是这次它不起作用,因为我的 Autowired dataSource 始终为空。但显然 spring boot 应该是自己配置的。

我坚持这篇教程帖子:https://www.baeldung.com/spring-boot-support-for-jooq

有人知道这里缺少什么吗?

POM.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>hotcueconverter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hotcueconverter</name>
    <description>hotcueconverter</description>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jooq</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

# Own settings
server.port=$8080
# H2 Database
spring.datasource.url=jdbc:h2:file:./db/MIKStore
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=test
spring.datasource.password=test
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=none
# H2 Console
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.h2.console.settings.trace=false
spring.h2.console.settings.web-allow-others=false
spring.jooq.sql-dialect=H2

ApplicationConfiguration.java

package com.example.hotcueconverter;

import javax.sql.DataSource;

import org.jooq.impl.DataSourceConnectionProvider;
import org.jooq.impl.DefaultConfiguration;
import org.jooq.impl.DefaultDSLContext;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

@Configuration
public class ApplicationConfiguration 

    @Autowired
    ExceptionTranslator exceptionTranslator;

    @Autowired
    private DataSource dataSource;

    @Bean
    public DefaultDSLContext defaultDSLContext() 
        return new DefaultDSLContext(this.configuration());
    

    @Bean
    public DataSourceConnectionProvider dataSourceConnectionProvider() 
        return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(this.dataSource));
    

    public DefaultConfiguration configuration() 
        final DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
        jooqConfiguration.set(this.dataSourceConnectionProvider());
        jooqConfiguration.set(new DefaultExecuteListenerProvider(this.exceptionTranslator));

        return jooqConfiguration;
    

由于教程中没有提到exceptionTransformer,所以我自己写了exceptionTranslator:

package com.example.hotcueconverter;

import javax.sql.DataSource;

import org.jooq.impl.DataSourceConnectionProvider;
import org.jooq.impl.DefaultConfiguration;
import org.jooq.impl.DefaultDSLContext;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

@Configuration
public class ApplicationConfiguration 

    @Autowired
    ExceptionTranslator exceptionTranslator;

    @Autowired
    private DataSource dataSource;

    @Bean
    public DefaultDSLContext defaultDSLContext() 
        return new DefaultDSLContext(this.configuration());
    

    @Bean
    public DataSourceConnectionProvider dataSourceConnectionProvider() 
        return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(this.dataSource));
    

    public DefaultConfiguration configuration() 
        final DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
        jooqConfiguration.set(this.dataSourceConnectionProvider());
        jooqConfiguration.set(new DefaultExecuteListenerProvider(this.exceptionTranslator));

        return jooqConfiguration;
    

我的 TestModule/Service 所在的数据 PS:this.loadFile只是加载sql脚本。

@Service
public class TestModule 

    private static final Logger LOGGER = LoggerFactory.getLogger(TestModule.class);
    private static final String MIKSTORE_FILENAME = "mikstore_export.sql";

    @Autowired
    DefaultDSLContext dslContext;

    public void test() throws Exception 
        final String fileAsString = this.loadFile(MIKSTORE_FILENAME);

        final Parser parser = this.dslContext.parser();
        final Queries queries = parser.parse(fileAsString);

        this.dslContext.execute(queries.toString());
    

任何帮助,即使它是实现此目的的另一种方式,将不胜感激! :)

谢谢!

【问题讨论】:

【参考方案1】:

UPD:

我发现了问题:D 我使用的是不是由 spring 管理的 DSL,因此它为 null,因为我没有自己初始化它。

我还在应用程序属性中设置了错误的休眠 DDL 属性。由于我想使用 jooq 创建架构和数据,我不得不将 hibernate auto ddl 设置为 none

【讨论】:

以上是关于使用 Spring Boot 进行 JOOQ SQL 语法转换的主要内容,如果未能解决你的问题,请参考以下文章

Spring boot、JOOQ和Flyway如何一起使用?

jooQ spring boot Multiple Schema(读写拆分)

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

如何使用 Spring-Boot config 配置 JOOQ 设置?

Spring Boot 上下文中的 Jooq CastException 已刷新

Spring Boot with JOOQ 和 Spring Data JPA 之间的技术差异