使用活动记录执行CRUD

本文是我们学院课程的一部分,标题为jOOQ –类型安全的数据库查询

在SQL和特定关系数据库很重要的Java应用程序中,jOOQ是一个不错的选择。 当JPA / Hibernate抽象过多,JDBC过多时,这是一种替代方法。 它显示了一种现代的领域特定语言如何可以极大地提高开发人员的生产率,从而将SQL内部化为Java。

在本课程中,我们将看到如何使用jOOQ有效地查询数据库。 在这里查看

1.简介

虽然SQL是一种非常有表现力的语言,但是您的大多数SQL可能都是CRUD(创建,读取,更新,删除)。 编写这样的CRUD既无聊又重复,这就是为什么像Hibernate这样的ORM出现并成功提高开发人员生产力的原因。 但是,当您经常只想对表中的单个记录进行操作时,Hibernate对您的体系结构进行了许多假设(和限制)。

也可以从org.jooq.academy.section2包中获得本节中显示的示例

2.简单的活动记录操作

jOOQ知道“活动记录”或UpdatableRecords ,可以将其装入“特殊”种类的SELECT语句,然后在内部跟踪脏标志。 这是在不编写过多SQL的DATE_OF_BIRTH下更新作者DATE_OF_BIRTH

AuthorRecord author = dsl.selectFrom(AUTHOR).where(AUTHOR.ID.eq(1)).fetchOne();
author.setDateOfBirth(Date.valueOf("2000-01-01"));
author.store();

由于上面的示例仅通过selectFrom()从一个表中进行选择,因此jOOQ知道结果记录类型将为AuthorRecord ,即由代码生成器生成的对象。 AuthorRecord实现UpdatableRecord ,它具有多种有用的方法:

以下示例部分将指导您完成创建,读取,更新,删除此类记录的整个生命周期:

AuthorRecord author;

// Create a new record and store it to the database. This will perform an INSERT statement
author = dsl.newRecord(AUTHOR);
author.setId(3);
author.setFirstName("Alfred");
author.setLastName("Hitchcock");
author.store();

// Read the record by refreshing it based on the primary key value
author = dsl.newRecord(AUTHOR);
author.setId(3);
author.refresh();

// Update the record with a new value
author.setDateOfBirth(Date.valueOf("1899-08-13"));
author.store();

// Delete the record again
author.delete();

jOOQ的UpdatableRecords跟踪每列内部的“脏”或“已更改”状态,在调用store()以便仅插入/更新已在UpdatableRecord更改的值时使用该状态。

3.乐观锁

执行CRUD时,并发数据访问通常是一个可以通过两种方法解决的问题:

  • 通过使用悲观锁定
  • 通过使用乐观锁定

悲观锁定很少是一个好选择,因为当两个进程以不同的顺序锁定表中的几行以等待彼此完成时,死锁很容易发生。 乐观锁定是更合适的解决方案。 一个过程可能很幸运,可以在另一个过程尝试(失败)之前完成交易。 这是jOOQ的工作方式。

在我们的样本数据中, BOOK表具有一个特殊的“系统”列,称为REC_TIMESTAMP 。 每当您在BookRecord上运行CRUD操作时,jOOQ都会完全管理此列的内容,而不必保持最新状态。 考虑以下代码示例:

// Enable optimistic locking
DSLContext dsl = DSL.using(connection, new Settings().withExecuteWithOptimisticLocking(true));

// Perform the CRUD with the above setting
BookRecord book1 = dsl.selectFrom(BOOK).where(BOOK.ID.eq(1)).fetchOne();
book1.setTitle("New Title");
book1.store();

jOOQ现在将执行一条UPDATE语句,该语句还将更新并检查REC_TIMESTAMP值:

update "PUBLIC"."BOOK"
set    "PUBLIC"."BOOK"."TITLE" = 'New Title',
       "PUBLIC"."BOOK"."REC_TIMESTAMP" = timestamp '2014-09-08 18:40:39.416'
where ("PUBLIC"."BOOK"."ID" = 1 and "PUBLIC"."BOOK"."REC_TIMESTAMP" is null)

注意如何在SET子句REC_TIMESTAMP设置为当前时间,同时在WHERE子句中还将其检查为NULL (示例数据库中的初始值)。

如果我们现在有两个相互竞争的进程(或同一进程中的代码部分)进行此更新,如下所示:

BookRecord book1 = dsl.selectFrom(BOOK).where(BOOK.ID.eq(1)).fetchOne();
BookRecord book2 = dsl.selectFrom(BOOK).where(BOOK.ID.eq(1)).fetchOne();

book1.setTitle("New Title");
book1.store();

book2.setTitle("Another Title");
book2.store();

…然后,在对store()的第二次调用(缩短的堆栈跟踪)上,我们将见证DataChangedException

org.jooq.exception.DataChangedException: Database record has been changed or doesn't exist any longer
    at org.jooq.impl.UpdatableRecordImpl.checkIfChanged(UpdatableRecordImpl.java:420)
    at org.jooq.impl.UpdatableRecordImpl.storeUpdate(UpdatableRecordImpl.java:193)
    at org.jooq.impl.UpdatableRecordImpl.store(UpdatableRecordImpl.java:129)
    at org.jooq.impl.UpdatableRecordImpl.store(UpdatableRecordImpl.java:121)

乐观锁定适用于UpdatableRecord操作,包括insert()update()delete()

jOOQ支持三种乐观锁定模式:

  • 使用专用的TIMESTAMP列来跟踪修改日期
  • 使用专用的NUMBER列跟踪版本号
  • 使用价值比较。 如果没有为代码生成器配置任何时间戳或版本列,则为默认设置

翻译自: https://www.javacodegeeks.com/2015/09/perform-crud-with-active-records.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值