Jooq 一次将 one2one 和 one2many 关系数据插入到 2 个表中。如何处理问题和回滚

Posted

技术标签:

【中文标题】Jooq 一次将 one2one 和 one2many 关系数据插入到 2 个表中。如何处理问题和回滚【英文标题】:Jooq insert one2one and one2many relational data into 2 tables at once. How to deal with issues and rollback 【发布时间】:2021-07-02 00:49:13 【问题描述】:

F.e.型号

class Author 
  id, name


class Book 
  id, title, author



create table author (
    id bigint not null auto_increment,
    name varchar,
    CONSTRAINT author_pk PRIMARY KEY (id),
);
create table book (
    id bigint not null auto_increment,
    title varchar,
    author_id bigint,
    CONSTRAINT book_pk PRIMARY KEY (id),
    CONSTRAINT book_fk_author FOREIGN KEY (author_id) REFERENCES author (id) ON DELETE NO ACTION ON UPDATE NO ACTION
)

如何在jooq中一次插入?如果某些查询失败,如何处理回滚? 它必须在我这边编程吗?我在文档中找不到关于这种情况的消息:(

我应该像这样手动操作:

    按名称在 db 中查找作者 ID 如果作者不存在插入新作者 插入带有作者 ID 的图书 如果书籍插入失败,那么如果这次插入则删除作者?

如何处理?你有这方面的例子吗?

编辑: 我用的是h2数据库

【问题讨论】:

您使用的是什么数据库产品?您的表的 DDL 定义是什么(包括例如 ID 列是否是身份等)? 我使用 h2。是的,存在基于主键和外键的关系。 id 由 db 自动生成 【参考方案1】:

数据库中的所有更改都是事务性的。

如果 on 操作失败,您可以回滚事务,然后数据库中将没有任何数据。所以不需要删除任何东西。

请阅读文档中有关事务管理的部分: https://www.jooq.org/doc/3.14/manual-single-page/#transaction-management

【讨论】:

【参考方案2】:

Simon 已经为您提供了有关您的逻辑事务性的反馈。您的 4 个步骤可以编码如下(假设您使用的是代码生成器):

// You probably have some DSLContext injected to your repository/dao/whatever somewhere
DSLContext ctx = ...

// 4. Start the transaction to make the contents atomic and roll back on failure
// In order to use a transactional configuration and DSLContext, make sure you don't use
// the "outer" DSLContext, which, depending on its Configuration might not be 
// transactional. E.g. it isn't transactional when it references a DataSource. It might
// be transactional (by accident), if it wraps a JDBC Connection.
ctx.transaction(c -> 

    // 1. try to find the author by ID. Alternatively, write a query
    AuthorRecord author = c.dsl().fetchOne(AUTHOR, AUTHOR.ID.eq(id));

    // 2. If the author wasn't found, create it
    if (author == null) 
        author = c.dsl().newRecord(AUTHOR);
        author.setName(name);

        // 2. This will store the author and by default, automatically fetch the 
        // generated ID
        author.store();
    

    // 3. Insert the book with the previously fetched author ID
    BookRecord book = c.dsl().newRecord(BOOK);
    book.setAuthorId(author.getId());
    book.setTitle(title);
    book.store();

当然,除了使用 jOOQ 事务 API,您还可以使用任何其他方式为您的代码提供事务性,包括直接使用 Spring、Java EE 或 JDBC。

【讨论】:

以上是关于Jooq 一次将 one2one 和 one2many 关系数据插入到 2 个表中。如何处理问题和回滚的主要内容,如果未能解决你的问题,请参考以下文章

如何一次将数据插入和更新到 EF 多个表中

一次将datagridview的所有数据插入数据库

如何一次将多个关系保存到 CoreData?

如何在 Odoo 8 中创建 One2one 关系?

如何使用 Codeigniter 3 一次将图像输入到 2 个表中

一次将多个文件上传到 Struts2 @Action