springboot中如何使用批量条件查询 springboot批量更新数据库_springboot批量更新实体


前面一篇介绍了 Jooq 的记录新增,除了利用自动生成的代码来保存数据之外,也可以借助DSL.table() + DSL.field()来实现类 sql 的写法;本文将介绍 curd 中的删除和更新的用法

I. 项目搭建

本项目借助SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA进行开发

1. 项目依赖

关于如何创建一个 SpringBoot 的项目工程,不再本文的描述范围内,如有兴趣可以到文末的个人站点获取

在这个示例工程中,我们的选用 h2dabase 作为数据库(方便有兴趣的小伙伴直接获取工程源码之后,直接测试体验),因此对应的 pom 核心依赖如下

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jooqartifactId>
    dependency>
    <dependency>
        <groupId>com.h2databasegroupId>
        <artifactId>h2artifactId>
    dependency>
dependencies>

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-jooqartifactId>
    dependency>
    <dependency>
        <groupId>com.h2databasegroupId>
        <artifactId>h2artifactId>
    dependency>
dependencies>

2. 数据库初始化

我们借助jooq-codegen-maven插件来自动生成数据库相关的代码,对这一段逻辑感兴趣的小伙伴可以参考博文:【DB 系列】Jooq 代码自动生成

后文中使用的表结构如下

DROP TABLE IF EXISTS poet;

CREATE TABLE poet (
  `id` int NOT NULL,
  `name` varchar(20) NOT NULL default '',
  CONSTRAINT pk_t_poet PRIMARY KEY (ID)
);

DROP TABLE IF EXISTS poetry;
CREATE TABLE poetry (
  `id` int NOT NULL,
  `poet_id` int NOT NULL default '0',
  `title` varchar(128) not null default '',
  `content` varchar(128) not null default '',
  CONSTRAINT pk_t_poetry PRIMARY KEY (ID)
);

DROP TABLE IF EXISTS poet;

CREATE TABLE poet (
  `id` int NOT NULL,
  `name` varchar(20) NOT NULL default '',
  CONSTRAINT pk_t_poet PRIMARY KEY (ID)
);

DROP TABLE IF EXISTS poetry;
CREATE TABLE poetry (
  `id` int NOT NULL,
  `poet_id` int NOT NULL default '0',
  `title` varchar(128) not null default '',
  `content` varchar(128) not null default '',
  CONSTRAINT pk_t_poetry PRIMARY KEY (ID)
);

3. 配置文件

h2database 的连接配置如 application.properties

#Database Configuration
spring.datasource.url=jdbc:h2:~/h2-jooq-poet
spring.datasource.username=test
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver


#jOOQ Configuration
spring.jooq.sql-dialect=H2


spring.datasource.initialization-mode=never
spring.datasource.continueOnError=true


##h2 web console设置
spring.datasource.platform=h2
#进行该配置后,h2 web consloe就可以在远程访问了。否则只能在本机访问。
spring.h2.console.settings.web-allow-others=true
#进行该配置,你就可以通过YOUR_URL/h2访问h2 web consloe
spring.h2.console.path=/h2
#进行该配置,程序开启时就会启动h2 web consloe
spring.h2.console.enabled=true

#Database Configuration
spring.datasource.url=jdbc:h2:~/h2-jooq-poet
spring.datasource.username=test
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver


#jOOQ Configuration
spring.jooq.sql-dialect=H2


spring.datasource.initialization-mode=never
spring.datasource.continueOnError=true


##h2 web console设置
spring.datasource.platform=h2
#进行该配置后,h2 web consloe就可以在远程访问了。否则只能在本机访问。
spring.h2.console.settings.web-allow-others=true
#进行该配置,你就可以通过YOUR_URL/h2访问h2 web consloe
spring.h2.console.path=/h2
#进行该配置,程序开启时就会启动h2 web consloe
spring.h2.console.enabled=true

4. 数据准备

后文中的测试数据,主要借助的是前面一篇新增的记录,db 中记录如下



springboot中如何使用批量条件查询 springboot批量更新数据库_自动生成_02

II. 记录更新

1. 类 sql 方式更新

下面这种链式写法和 sql 极为相似

private static final PoetTB table = PoetTB.POET;

@Autowired
private DSLContext dsl;

private boolean updateName(int id, String name) {
    // ==> update poet set `name`=xx where id=xxx
    return dsl.update(table).set(table.NAME, name).where(table.ID.eq(id)).execute() > 0;
}

private static final PoetTB table = PoetTB.POET;

@Autowired
private DSLContext dsl;

private boolean updateName(int id, String name) {
    // ==> update poet set `name`=xx where id=xxx
    return dsl.update(table).set(table.NAME, name).where(table.ID.eq(id)).execute() > 0;
}

2. 更新计算

上面的更新方式属于最基本的直接设置,某些场景下我们可能需要借助之前的 column value,如下 concat 方法的更新方式,注意这个方法有Field提供

private boolean updateName2(int id, String name) {
    // concat 修改
    // 等同于 ==> update poet set `name`=concat(`name`, xxx) where id=xxx
    return dsl.update(table).set(table.NAME, table.NAME.concat(name)).where(table.ID.eq(id)).execute() > 0;
}

private boolean updateName2(int id, String name) {
    // concat 修改
    // 等同于 ==> update poet set `name`=concat(`name`, xxx) where id=xxx
    return dsl.update(table).set(table.NAME, table.NAME.concat(name)).where(table.ID.eq(id)).execute() > 0;
}

3. UpdateQuery 更新

除了上面的链式更新方式,还可以借助UpdateQuery来处理

private boolean updateName3(int id, String name) {
    // update query方式
    UpdateQuery updateQuery = dsl.updateQuery(table);
    // 这个表示需要更新的value
    updateQuery.addValue(table.NAME, name);
    // 这个表示where条件
    updateQuery.addConditions(table.ID.eq(id));
    // 最终通过execute执行更新操作
    return updateQuery.execute() > 0;
}

private boolean updateName3(int id, String name) {
    // update query方式
    UpdateQuery updateQuery = dsl.updateQuery(table);
    // 这个表示需要更新的value
    updateQuery.addValue(table.NAME, name);
    // 这个表示where条件
    updateQuery.addConditions(table.ID.eq(id));
    // 最终通过execute执行更新操作
    return updateQuery.execute() > 0;
}

4. Entity 更新

直接借助代码自动生成的 Record 类,本文中对应的是PO结尾的类

/**
 * 使用Entity进行更新
 *
 * @param id
 * @param name
 * @return
 */
private boolean updateName4(int id, String name) {
    // 请注意po对象由dsl生成,不能直接new一个对象
    PoetPO poetPO = dsl.newRecord(table);
    poetPO.setId(id);
    poetPO.setName(name);
    return poetPO.update() > 0;
}

/**
 * 使用Entity进行更新
 *
 * @param id
 * @param name
 * @return
 */
private boolean updateName4(int id, String name) {
    // 请注意po对象由dsl生成,不能直接new一个对象
    PoetPO poetPO = dsl.newRecord(table);
    poetPO.setId(id);
    poetPO.setName(name);
    return poetPO.update() > 0;
}

5. executeUpdate 更新

同样是借助 Record 类,与上面的区别在于这个实体类直接 new 出来,借助dsl.executeUpdate执行更新

private boolean updateName5(int id, String name) {
    PoetPO po = new PoetPO();
    po.setName(name);
    return dsl.executeUpdate(po, table.ID.eq(id)) > 0;
}

private boolean updateName5(int id, String name) {
    PoetPO po = new PoetPO();
    po.setName(name);
    return dsl.executeUpdate(po, table.ID.eq(id)) > 0;
}

6. 批量更新

请注意这里说的批量更新不是指一条 sql 更新多条 record 记录,更像是多个更新 sql 的一次提交执行

下面主要是借助dsl.batchUpdate来实现

/**
 * 批量更新
 *
 * @param list
 * @return
 */
private boolean batchUpdate(List list) {
    List poList = list.stream().map(this::bo2po).collect(Collectors.toList());int[] ans = dsl.batchUpdate(poList).execute();
    System.out.println(JSONObject.toJSONString(ans));return true;
}private PoetPO bo2po(PoetBO bo) {
    PoetPO po = dsl.newRecord(table);
    po.setId(bo.getId());
    po.setName(bo.getName());return po;
}
/**
 * 批量更新
 *
 * @param list
 * @return
 */
private boolean batchUpdate(List list) {
    List poList = list.stream().map(this::bo2po).collect(Collectors.toList());int[] ans = dsl.batchUpdate(poList).execute();
    System.out.println(JSONObject.toJSONString(ans));return true;
}private PoetPO bo2po(PoetBO bo) {
    PoetPO po = dsl.newRecord(table);
    po.setId(bo.getId());
    po.setName(bo.getName());return po;
}

III. 记录删除

在实际的业务开发中,一般不建议直接删除记录,最好是通过一个 column 来标记逻辑删除,当然我们下面介绍的依然是物理删除...

1. 类 sql 写法

/**
 * 指定主键删除
 *
 * @param id
 * @return
 */
private boolean remove(int id) {
    return dsl.delete(table).where(table.ID.eq(id)).execute() > 0;
}

/**
 * 指定主键删除
 *
 * @param id
 * @return
 */
private boolean remove(int id) {
    return dsl.delete(table).where(table.ID.eq(id)).execute() > 0;
}

2. Entity 删除

直接借助自动生成的实体类来执行删除

private boolean remove2(int id) {
    PoetPO po = dsl.newRecord(table);
    po.setId(id);
    return po.delete() > 0;
}

private boolean remove2(int id) {
    PoetPO po = dsl.newRecord(table);
    po.setId(id);
    return po.delete() > 0;
}

3. dsl.executeDelete

借助dsl.executeDelete来删除实体类,与上面的区别在于这个实体类是直接 new 出来的

private boolean remove3(int id) {
    PoetPO po = new PoetPO();
    po.setId(id);
    return dsl.executeDelete(po) > 0;
}

private boolean remove3(int id) {
    PoetPO po = new PoetPO();
    po.setId(id);
    return dsl.executeDelete(po) > 0;
}

4. deleteQuery

private boolean remove4(int id) {
    DeleteQuery query = dsl.deleteQuery(table);
    query.addConditions(table.ID.ge(id));
    return query.execute() > 0;
}

private boolean remove4(int id) {
    DeleteQuery query = dsl.deleteQuery(table);
    query.addConditions(table.ID.ge(id));
    return query.execute() > 0;
}