Jooq 一次将 one2one 和 one2many 关系数据插入 2 个表。如何处理问题和回滚
Jooq insert one2one and one2many relational data into 2 tables at once. How to deal with issues and rollback
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中一次插入?如果某些查询将失败,如何处理回滚?
它必须在我这边编程吗?我在文档中找不到关于这种情况的词:(
我应该像这样手动操作吗:
- 通过名称在数据库中查找作者 ID
- 如果作者不存在插入新作者
- 插入带有作者 ID 的图书
- 如果插入图书失败,那么删除作者,如果这次插入了?
如何处理?你有这方面的例子吗?
编辑:
我使用h2数据库
数据库中的所有更改都是事务性的。
如果操作失败,您可以回滚事务,然后 none 的数据将在数据库中。所以不需要删除任何东西。
请阅读文档中有关事务管理的部分:
https://www.jooq.org/doc/3.14/manual-single-page/#transaction-management
已经为您提供了有关逻辑事务性的反馈。您的 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直接。
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中一次插入?如果某些查询将失败,如何处理回滚? 它必须在我这边编程吗?我在文档中找不到关于这种情况的词:(
我应该像这样手动操作吗:
- 通过名称在数据库中查找作者 ID
- 如果作者不存在插入新作者
- 插入带有作者 ID 的图书
- 如果插入图书失败,那么删除作者,如果这次插入了?
如何处理?你有这方面的例子吗?
编辑: 我使用h2数据库
数据库中的所有更改都是事务性的。
如果操作失败,您可以回滚事务,然后 none 的数据将在数据库中。所以不需要删除任何东西。
请阅读文档中有关事务管理的部分: https://www.jooq.org/doc/3.14/manual-single-page/#transaction-management
// 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直接。