jOOQ,是一个ORM框架,利用其生成的Java代码和流畅的API,可以快速构建有类型约束的安全的SQL语句
jOOQ使我们的重心可以放在业务逻辑上,而Java与SQL的基础交互部分,都可以交给jOOQ去处理。jOOQ通用支持很多数据库,而且有商业版本和社区版本区别,商业版本和社区版本区别主要是支持数据库不一样,可以在其授权说明页面上看到各个版本对于数据库的支持情况,开源版本只支持部分开源数据库如MySQL等,这已经能满足大部分公司需求,本系列教程也是基于MySQL数据库进行
jOOQ的核心优势是可以将数据库表结构映射为Java类,包含表的基本描述和所有表字段。通过jOOQ提供的API,配合生成的Java代码,可以很方便的进行数据库操作
生成的Java代码字段类型是根据数据库映射成的Java类型,在进行设置和查询操作时,因为是Java代码,都会有强类型校验,所以对于数据的输入,是天然安全的,极大的减少了SQL注入的风险
jOOQ的代码生成策略是根据配置全量生成,任何对于数据库的改动,如果会影响到业务代码,在编译期间就会被发现,可以及时进行修复
在当前微服务盛行的情况下,Spring Boot
或 Spring Cloud
为基础的微服务体系是主流, 也是目前业务场景中新的选型方向
相对于直接使用Spring来说,利用Spring Boot来整合jOOQ相对来说简单很多
Spring Boot 官方有对 jOOQ 的支持,所以只需要简单的引用 spring-boot-starter-jooq
和对应的jdbc驱动即可
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jooq</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
Spring Boot最大的一个特性就是有很多 AutoConfiguration
自动配置, spring-boot-starter-jooq
依赖于 spring-boot-starter-jdbc
, 其自动配置了数据源,事务管理器等
spring-boot-starter-jooq
自动配置了 org.jooq.Configuration
和 org.jooq.DSLContext
对象。 我们只需要在 src/main/resources/application.yml
内写好数据源相关配置,其他的一切都可以交给Spring Boot进行处理
src/main/resources/application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/learn-jooq?serverTimezone=GMT%2B8
username: root
password: root
直接通过main方法启动 Spring Boot 服务
@SpringBootApplication
public class Section8Main {
public static void main(String[] args) {
SpringApplication.run(Section8Main.class);
}
}
测试用例内,使用 SpringBootTest
注解
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Section8Main.class)
@Transactional
@Rollback
public class BaseTest {
@Autowired
DSLContext dslContext;
@Autowired
Configuration configuration;
@Autowired
TransactionManager transactionManager;
@Test
public void empty() {
Assertions.assertNotNull(dslContext);
Assertions.assertNotNull(configuration);
Assertions.assertNotNull(transactionManager);
}
}
JooqAutoConfiguration
源码解析以下是jOOQ的自动配置源码,从 spring-boot-autoconfigure
内拷贝而来,可以看出此配置会在数据源配置和事务配置之后执行
对于我们经常用到的就是 Bean dslContext
和 jooqConfiguration
,大部分自动配置的Bean都会使用 @ConditionalOnMissingBean
注解, 此注解标识在没有某个Bean的情况下,才会执行该注解所标注的配置
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration
/**
* {@link EnableAutoConfiguration Auto-configuration} for JOOQ.
*
* @author Andreas Ahlenstorf
* @author Michael Simons
* @author Dmytro Nosan
* @since 1.3.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DSLContext.class)
@ConditionalOnBean(DataSource.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, TransactionAutoConfiguration.class })
public class JooqAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConnectionProvider.class)
public DataSourceConnectionProvider dataSourceConnectionProvider(DataSource dataSource) {
return new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource));
}
@Bean
@ConditionalOnBean(PlatformTransactionManager.class)
public SpringTransactionProvider transactionProvider(PlatformTransactionManager txManager) {
return new SpringTransactionProvider(txManager);
}
@Bean
@Order(0)
public DefaultExecuteListenerProvider jooqExceptionTranslatorExecuteListenerProvider() {
return new DefaultExecuteListenerProvider(new JooqExceptionTranslator());
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DSLContext.class)
@EnableConfigurationProperties(JooqProperties.class)
public static class DslContextConfiguration {
@Bean
public DefaultDSLContext dslContext(org.jooq.Configuration configuration) {
return new DefaultDSLContext(configuration);
}
@Bean
@ConditionalOnMissingBean(org.jooq.Configuration.class)
public DefaultConfiguration jooqConfiguration(JooqProperties properties, ConnectionProvider connectionProvider,
DataSource dataSource, ObjectProvider<TransactionProvider> transactionProvider,
ObjectProvider<RecordMapperProvider> recordMapperProvider,
ObjectProvider<RecordUnmapperProvider> recordUnmapperProvider, ObjectProvider<Settings> settings,
ObjectProvider<RecordListenerProvider> recordListenerProviders,
ObjectProvider<ExecuteListenerProvider> executeListenerProviders,
ObjectProvider<VisitListenerProvider> visitListenerProviders,
ObjectProvider<TransactionListenerProvider> transactionListenerProviders,
ObjectProvider<ExecutorProvider> executorProvider) {
DefaultConfiguration configuration = new DefaultConfiguration();
configuration.set(properties.determineSqlDialect(dataSource));
configuration.set(connectionProvider);
transactionProvider.ifAvailable(configuration::set);
recordMapperProvider.ifAvailable(configuration::set);
recordUnmapperProvider.ifAvailable(configuration::set);
settings.ifAvailable(configuration::set);
executorProvider.ifAvailable(configuration::set);
configuration.set(recordListenerProviders.orderedStream().toArray(RecordListenerProvider[]::new));
configuration.set(executeListenerProviders.orderedStream().toArray(ExecuteListenerProvider[]::new));
configuration.set(visitListenerProviders.orderedStream().toArray(VisitListenerProvider[]::new));
configuration.setTransactionListenerProvider(
transactionListenerProviders.orderedStream().toArray(TransactionListenerProvider[]::new));
return configuration;
}
}
}
如果我们需要使用多数据源,可以在启动入口中的 @SpringBootApplication
中使用 exclude
选项,不让 Spring Boot 自动配置数据源和 jOOQ 的配置。最后参考一下上一篇多数据源的文章内容,然后进行同样的配置即可,Spring Boot 本质上也是对 Spring 框架的整合而已
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
JooqAutoConfiguration.class,
TransactionAutoConfiguration.class})