【问题标题】:How to reverse engineer a database and generate code using spring boot and jOOQ?如何使用 Spring Boot 和 jOOQ 对数据库进行逆向工程并生成代码?
【发布时间】:2016-09-20 08:44:08
【问题描述】:

简介

在阅读了一些博客并观看了一些关于 jOOQ 的演示之后,我非常兴奋地尝试了逆向工程 api 并替换了我目前用来对数据库进行逆向工程的 hibernate 工具。

基于 Petri Kainulainen http://www.petrikainulainen.net/programming/jooq/using-jooq-with-spring-configuration/ 的示例配置和 jOOQ https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-spring-boot-example 的创始人对 Spring Boot 的友好改编,我尝试设置一个 spring-boot-starter-jdbc,目标是从mysql 数据库(来自 MySQL 网站的 sakila 示例)。

使用 mvn clean install 运行程序和/或仅将其作为 Spring Boot 应用程序运行时,不会发生代码生成。标准 Spring Boot 应用程序运行,没有显示错误和/或警告。

[2m2016-05-23 14:07:50.604[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[           main][0;39m [36mn.sander.mieras.application.Application [0;39m [2m:[0;39m Starting Application on MacBook-Pro-van-Sander.local with PID 628 (/Users/Sander/Development/Workspace/reverse-engineer-jooq/target/classes started by Sander in /Users/Sander/Development/Workspace/reverse-engineer-jooq)
[2m2016-05-23 14:07:50.606[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[           main][0;39m [36mn.sander.mieras.application.Application [0;39m [2m:[0;39m No active profile set, falling back to default profiles: default
[2m2016-05-23 14:07:50.641[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[           main][0;39m [36ms.c.a.AnnotationConfigApplicationContext[0;39m [2m:[0;39m Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@11e21d0e: startup date [Mon May 23 14:07:50 CEST 2016]; root of context hierarchy
[2m2016-05-23 14:07:51.451[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[           main][0;39m [36mo.s.j.e.a.AnnotationMBeanExporter       [0;39m [2m:[0;39m Registering beans for JMX exposure on startup
[2m2016-05-23 14:07:51.460[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[           main][0;39m [36mn.sander.mieras.application.Application [0;39m [2m:[0;39m Started Application in 1.036 seconds (JVM running for 1.66)
[2m2016-05-23 14:07:51.461[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[       Thread-1][0;39m [36ms.c.a.AnnotationConfigApplicationContext[0;39m [2m:[0;39m Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@11e21d0e: startup date [Mon May 23 14:07:50 CEST 2016]; root of context hierarchy
[2m2016-05-23 14:07:51.463[0;39m [32m INFO[0;39m [35m628[0;39m [2m---[0;39m [2m[       Thread-1][0;39m [36mo.s.j.e.a.AnnotationMBeanExporter       [0;39m [2m:[0;39m Unregistering JMX-exposed beans on shutdown

给定

来自 jOOQ-spring-boot-example 的 pom.xml 构建配置,带有一些调整后的配置(为了便于阅读,省略了一些标准依赖项)

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

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>properties-maven-plugin</artifactId>
                <version>1.0.0</version>
                <executions>
                  <execution>
                    <phase>initialize</phase>
                    <goals>
                      <goal>read-project-properties</goal>
                    </goals>
                    <configuration>
                      <files>
                        <file>src/main/resources/application.properties</file>
                      </files>
                    </configuration>
                  </execution>
                </executions>
              </plugin>

            <plugin>
                <groupId>org.jooq</groupId>
                <artifactId>jooq-codegen-maven</artifactId>                     
                <executions>
                    <execution>
                        <id>reverse-engineer</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <jdbc>
                                <driver>${db.driver}</driver>
                                <url>${db.url}</url>
                                <user>${db.username}</user>
                                <password>${db.password}</password>
                            </jdbc>
                            <generator>
                                <database>
                                    <name>${jooq.generator.db.dialect}</name>
                                    <includes>.*</includes>
                                    <excludes></excludes>
                                    <dateAsTimestamp>true</dateAsTimestamp>
                                    <inputSchema>SAKILA</inputSchema>
                                </database>
                                <generate>
                                    <deprecated>false</deprecated>
                                    <instanceFields>true</instanceFields>
                                    <pojos>true</pojos>
                                    <records>true</records>
                                </generate>
                                <target>
                                    <packageName>nl.sander.mieras.domain</packageName>
                                    <directory>src/main/java</directory>
                                </target>
                            </generator>
                        </configuration>
                     </execution>
                </executions>           
                <dependencies>                  
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>                      
                    </dependency>
                </dependencies>             
            </plugin>
        </plugins>
    </pluginManagement>  
</build>

鉴于我的主要配置类看起来像这样(所有的 bean 代码都取自 jOOQ-spring-boot-example):

@Configuration
// not sure if I need this setting since I initialize it in the pom build
@PropertySource("classpath:application.properties") 
@Import({SpringTransactionProvider.class, ExceptionTranslator.class})
public class JooqSpringBootConfiguration {

    @Autowired
    private Environment env;    

    @Autowired
    private SpringTransactionProvider txp;

    @Autowired
    private ExceptionTranslator ext;

    @Bean(destroyMethod = "close")
    public DataSource dataSource() throws IllegalStateException, PropertyVetoException{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(env.getRequiredProperty("db.driver"));
        dataSource.setJdbcUrl(env.getRequiredProperty("db.url"));
        dataSource.setUser(env.getRequiredProperty("db.username"));
        dataSource.setPassword("db.password");

        return dataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource) throws IllegalStateException, PropertyVetoException{
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public DSLContext dsl(org.jooq.Configuration config){
        return new DefaultDSLContext(config);
    }

    @Bean
    public ConnectionProvider connectionProvider(DataSource dataSource){
        return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource));
    }

    @Bean
    public ExecuteListenerProvider executeListenerProvider(ExceptionTranslator exceptionTranslator){
        return new DefaultExecuteListenerProvider(ext);
    }

    @Bean
    public org.jooq.Configuration jooqConfig(ConnectionProvider connectionProvider, TransactionProvider transactionProvider, ExecuteListenerProvider executeListenerProvider){

        return new DefaultConfiguration()
                .derive(connectionProvider)
                .derive(txp)
                .derive(executeListenerProvider)
                .derive(SQLDialect.MYSQL);
    }

}

最后但并非最不重要的是 source/main/resources 目录中的 application.properties 文件:

#Database Configuration
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/SAKILA?useSSL=false
db.username=root
db.password=****

#jOOQ Configuration
jooq.generator.db.dialect=MYSQL

问题

鉴于上述配置,我错过/和/或错误配置了哪些配置以启用代码生成(例如 POJO)?

【问题讨论】:

    标签: java mysql spring spring-jdbc jooq


    【解决方案1】:

    根据https://github.com/sivaprasadreddy/springboot-tutorials/tree/master/springboot-jooq-demo的示例找到了我的问题的解决方案

    我只需要一个配置良好的 pom,不需要实际的 java 代码。

    只需使用 clean install with profile reverse,它就会生成我想要的代码。

    pom(配置文件中 id 为“reverse”的插件):

    <plugin>
        <groupId>org.jooq</groupId>
        <artifactId>jooq-codegen-maven</artifactId>
        <executions>
            <execution>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
        <dependencies>
            <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
            </dependency>                           
        </dependencies>
        <configuration>
            <jdbc>
                <driver>com.mysql.jdbc.Driver</driver>
                <url>jdbc:mysql://localhost:3306/sakila</url>
                <user>root</user>
                <password>****</password>
            </jdbc>
        <generator>
        <name>org.jooq.util.DefaultGenerator</name>
             <database>
                 <name>org.jooq.util.mysql.MySQLDatabase</name>
                 <includes>.*</includes>
                 <excludes />
                 <inputSchema>sakila</inputSchema>
             </database>
        <generate>
            <deprecated>false</deprecated>      
            <jpaAnnotations>false</jpaAnnotations>  
            <validationAnnotations>true</validationAnnotations>     
            <instanceFields>false</instanceFields>   
            <records>false</records>            
            <immutablePojos>false</immutablePojos>
            <relations>true</relations>
            <globalObjectReferences>false</globalObjectReferences>
            <pojos>true</pojos>                                 
        </generate>
        <target>
            <packageName>nl.sander.mieras.domain</packageName>
            <directory>src/main/java</directory>
        </target>
        </generator>
      </configuration>
    </plugin>
    

    以及应用程序:

    package nl.sander.mieras.application;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) throws Exception {
            SpringApplication.run(Application.class, args);
        }
    }
    

    【讨论】:

      【解决方案2】:

      更新为:

      • SpringBoot 2.1.8.RELEASE
      • JOOQ 3.12.1
      • PostgreSQL 9.6

      Maven 命令: mvn clean install -Preverse

      Application.properties

      #Database Configuration
      spring.datasource.url=jdbc:postgresql://localhost:5432/my-database
      spring.datasource.username=db-user
      spring.datasource.password=db-password
      # The SQL dialect makes Hibernate generate better SQL for the chosen database
      spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
      # Hibernate ddl auto (create, create-drop, validate, update)
      spring.jpa.hibernate.ddl-auto=update
      spring.datasource.driver-class-name=org.postgresql.Driver
      #jOOQ Configuration
      spring.jooq.sql-dialect=POSTGRES
      

      Maven pom.xml

      <properties>
              <java.version>1.8</java.version>
              <jooq.version>3.12.1</jooq.version>
          </properties>
      
          <dependencies>
              <!--JOQQ -->
              <dependency>
                  <groupId>org.jooq</groupId>
                  <artifactId>jooq</artifactId>
                  <version>${jooq.version}</version>
              </dependency>
              <dependency>
                  <groupId>org.jooq</groupId>
                  <artifactId>jooq-meta</artifactId>
                  <version>${jooq.version}</version>
              </dependency>
              <dependency>
                  <groupId>org.jooq</groupId>
                  <artifactId>jooq-codegen</artifactId>
                  <version>${jooq.version}</version>
              </dependency>
              <!--JOQQ -->
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-data-jpa</artifactId>
              </dependency>
      
              <dependency>
                  <groupId>org.postgresql</groupId>
                  <artifactId>postgresql</artifactId>
                  <version>${postgresql.version}</version>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-validation</artifactId>
              </dependency>
      
          </dependencies>
      
      
          <profiles>
              <profile>
                  <id>reverse</id>
                  <build>
                      <plugins>
                          <plugin>
                              <groupId>org.jooq</groupId>
                              <artifactId>jooq-codegen-maven</artifactId>
                              <version>${jooq.version}</version>
                              <executions>
                                  <execution>
                                      <goals>
                                          <goal>generate</goal>
                                      </goals>
                                  </execution>
                              </executions>
                              <configuration>
                                  <jdbc>
                                      <driver>org.postgresql.Driver</driver>
                                      <url>jdbc:postgresql://localhost:5432/avro</url>
                                      <user>avro</user>
                                      <password>avro</password>
                                  </jdbc>
                                  <generator>
                                      <name>org.jooq.codegen.DefaultGenerator</name>
                                      <database>
                                          <name>org.jooq.meta.postgres.PostgresDatabase</name>
                                          <inputSchema>public</inputSchema>
                                          <includes>.*</includes>
                                          <excludes/>
                                      </database>
                                      <generate>
                                          <deprecated>false</deprecated>
                                          <jpaAnnotations>false</jpaAnnotations>
                                          <validationAnnotations>true</validationAnnotations>
                                          <instanceFields>false</instanceFields>
                                          <records>false</records>
                                          <immutablePojos>false</immutablePojos>
                                          <relations>true</relations>
                                          <globalObjectReferences>false</globalObjectReferences>
                                          <pojos>true</pojos>
                                      </generate>
                                      <target>
                                          <packageName>com.example.domain</packageName>
                                          <directory>src/main/java</directory>
                                      </target>
                                  </generator>
                              </configuration>
                          </plugin>
                      </plugins>
                  </build>
              </profile>
          </profiles>
      
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-maven-plugin</artifactId>
                  </plugin>
                  <plugin>
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-compiler-plugin</artifactId>
                      <configuration>
                          <source>9</source>
                          <target>9</target>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      

      JOOQ 配置类

      @Configuration
      @Import({SpringTransactionProvider.class})
      @PropertySource("classpath:application.properties")
      public class JooqSpringBootConfiguration {
      
          private final Environment env;
      
          @Autowired
          public JooqSpringBootConfiguration(Environment env) {
              this.env = env;
          }
      
          @Bean
          public DataSource dataSource() throws IllegalStateException {
      
              HikariDataSource dataSource = new HikariDataSource();
              dataSource.setDriverClassName(env.getRequiredProperty("spring.datasource.driver-class-name"));
              dataSource.setJdbcUrl(env.getRequiredProperty("spring.datasource.url"));
              dataSource.setUsername(env.getRequiredProperty("spring.datasource.username"));
              dataSource.setPassword(env.getRequiredProperty("spring.datasource.password"));
      
              return dataSource;
          }
      
          @Bean
          public LazyConnectionDataSourceProxy lazyConnectionDataSource() {
              return new LazyConnectionDataSourceProxy(dataSource());
          }
      
          @Bean
          public TransactionAwareDataSourceProxy transactionAwareDataSource() {
              return new TransactionAwareDataSourceProxy(lazyConnectionDataSource());
          }
      
          @Bean
          public DataSourceTransactionManager transactionManager() {
              return new DataSourceTransactionManager(lazyConnectionDataSource());
          }
      
          @Bean
          public DataSourceConnectionProvider connectionProvider() {
              return new DataSourceConnectionProvider(transactionAwareDataSource());
          }
      
          @Bean
          public JOOQToSpringExceptionTransformer jooqToSpringExceptionTransformer() {
              return new JOOQToSpringExceptionTransformer();
          }
      
          @Bean
          public DefaultConfiguration configuration() {
              DefaultConfiguration jooqConfiguration = new DefaultConfiguration();
      
              jooqConfiguration.set(connectionProvider());
              jooqConfiguration.set(new DefaultExecuteListenerProvider(
                      jooqToSpringExceptionTransformer()
              ));
      
              String sqlDialectName = env.getRequiredProperty("spring.jooq.sql-dialect");
              SQLDialect dialect = SQLDialect.valueOf(sqlDialectName);
              jooqConfiguration.set(dialect);
      
              return jooqConfiguration;
          }
      
          @Bean
          public DefaultDSLContext dsl() {
              return new DefaultDSLContext(configuration());
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-20
        • 1970-01-01
        • 1970-01-01
        • 2011-05-28
        • 2014-09-30
        • 2014-02-22
        • 2010-09-16
        相关资源
        最近更新 更多