本文是我们学院课程的一部分,标题为jOOQ –类型安全的数据库查询 。
在SQL和特定关系数据库很重要的Java应用程序中,jOOQ是一个不错的选择。 当JPA / Hibernate抽象过多,JDBC过多时,这是一种替代方法。 它显示了一种现代的领域特定语言如何可以极大地提高开发人员的生产率,从而将SQL内部化为Java。
在本课程中,我们将看到如何使用jOOQ有效地查询数据库。 在这里查看 !
1.简介
有多种SPI( 服务提供商接口 ),可用于管理jOOQ中各种实体的生命周期。 可以通过Configuration
对象注入这些SPI。 在本节中,我们将学习这些生命周期管理对象如何与jOOQ交互。
也可以从org.jooq.academy.section4包中获得本节中显示的示例 。
2. ConnectionProvider
最重要的SPI是为jOOQ提供JDBC Connection
SPI。 到目前为止,在示例中, Connection
已直接传递到DSL.using()
方法:
DSLContext dsl = DSL.using(connection);
对于更详细的变体(将connection
包装在DefaultConnectionProvider
此符号只是一个方便:
DSLContext dsl = DSL.using(new DefaultConfiguration().set(new DefaultConnectionProvider(connection)));
在比本教程更复杂的设置中,您可能希望为jOOQ提供一个DataSource
,例如在使用Connection
池时,甚至在通过JTA使用分布式事务时。 还通过便利方法以本机方式支持涉及DataSources
流行用例(尽管您需要提供SQLDialect
,因为它不能从DataSource
派生。
DSLContext dsl = DSL.using(dataSource, SQLDialect.H2);
如果您希望实现任何其他类型的JDBC Connection
源,则可以实现自己的ConnectionProvider
public interface ConnectionProvider {
// jOOQ will acquire a connection through this method prior to query execution
Connection acquire() throws DataAccessException;
// jOOQ will release previously acquired connections again through this method after query execution
void release(Connection connection) throws DataAccessException;
}
3. SQLDialect
jOOQ将在具体的SQLDialect上下文中生成并执行您的SQL语句。 运行以下程序时,可以通过示例来最好地说明这一点:
// This renders SELECT 1 / SELECT 1 FROM DUAL in various SQL dialect families
Arrays.stream(SQLDialect.families())
.map(family -> String.format("%9s : ", family) + DSL.using(family).render(DSL.selectOne()))
.forEach(System.out::println);
当您执行上述程序时,您可能会得到类似以下内容的信息:
ACCESS : select 1 as [one] from (select count(*) dual from MSysResources) as dual
ASE : select 1 [one]
CUBRID : select 1 "one" from "db_root"
DB2 : select 1 "one" from "SYSIBM"."DUAL"
DERBY : select 1 as "one" from "SYSIBM"."SYSDUMMY1"
FIREBIRD : select 1 "one" from "RDB$DATABASE"
H2 : select 1 "one" from dual
INFORMIX : select 1 "one" from (select 1 as dual from systables where tabid = 1) as dual
INGRES : select 1 "one" from (select 1 as dual) as dual
HSQLDB : select 1 as "one" from "INFORMATION_SCHEMA"."SYSTEM_USERS"
MARIADB : select 1 as `one` from dual
MYSQL : select 1 as `one` from dual
ORACLE : select 1 "one" from dual
POSTGRES : select 1 as "one"
SQLITE : select 1 one
SQLSERVER : select 1 [one]
SYBASE : select 1 [one] from [SYS].[DUMMY]
这些语句都是从相同的jOOQ DSL表达式DSL.selectOne()
。 在大多数情况下,您无需担心各种SQL方言之间的细微差别,因为jOOQ会在单个API中将它们抽象出来。
您的SQLDialect
是否支持任何给定的jOOQ API元素,可以从大多数DSL方法上的@Support
注释中看出。 采用DSL.denseRank()
方法,该方法为DENSE_RANK()
窗口函数建模。 在jOOQ API中声明为:
@Support({ CUBRID, DB2, INFORMIX, POSTGRES, ORACLE, SQLSERVER, SYBASE })
public static WindowOverStep<Integer> rank() { ... }
4.设定
设置用于向jOOQ提供有关常规查询呈现和执行行为的信息。 它们受XSD的控制,可从以下位置获得:XSD: http : //www.jooq.org/xsd/jooq-runtime-3.3.0.xsd (请查看最新手册或网站以获取潜在更新)
在其当前版本中,jOOQ设置包含用于管理…的标志。
- 表是否应完全使用架构限定
- 表和模式是否应该转换/映射(例如,实现多租户)
- 是否应引用模式,表和列名称(例如,以支持区分大小写的名称)
- 生成的SQL关键字是大写还是小写
- 是否应格式化生成的SQL(例如用于调试日志记录)
- 绑定值应呈现为问号,命名参数还是内联
- 应该执行静态语句还是预备语句
- 执行记录是否处于活动状态
- 乐观锁定是否处于活动状态
- 活动记录是否应保留对产生它们的
Configuration
的引用 - 活动记录是否具有可更新的主键
- 是否应该缓存反射信息
5. ExecuteListeners
ExecuteListener
是几个SPI( 服务提供者接口)之一 ,您可以使用它们在更高层次上连接jOOQ的查询呈现,变量绑定和执行生命周期。 以下示例显示了一种简单的方法,可以根据每个查询衡量查询执行时间。
示例ExecuteListener
ExecuteListener listener = new DefaultExecuteListener() {
@Override
public void start(ExecuteContext ctx) {
// Register the start time to the current context
ctx.data("time", System.nanoTime());
}
@Override
public void end(ExecuteContext ctx) {
// Extract the start time from the current context
Long time = (Long) ctx.data("time");
System.out.println("Execution time : " + ((System.nanoTime() - time) / 1000 / 1000.0) + "ms. Query : " + ctx.sql());
}
};
然后可以在Configuration
使用此侦听Configuration
,如下所示:
DSL.using(new DefaultConfiguration()
.set(SQLDialect.H2)
.set(new DefaultConnectionProvider(connection))
.set(new DefaultExecuteListenerProvider(listener))
)
.select(AUTHOR.ID)
.from(AUTHOR)
.fetch();
现在,对fetch()
的调用将启动整个查询执行生命周期,包括已实现的start()
和end()
回调。 这将导致在控制台上显示以下内容:
Execution time : 0.101ms. Query : select "PUBLIC"."AUTHOR"."ID" from "PUBLIC"."AUTHOR"
针对特定用例还有其他SPI。 有关这些的详细信息,请参阅jOOQ手册 。
翻译自: https://www.javacodegeeks.com/2015/09/the-jooq-configuration.html