Skip to main content

新增操作

使用 dbVisitor 构造器新增数据时允许使用实体 Bean 或者使用 Map 作为新数据的容器。

使用 Bean 作为数据容器
User user = new User();
user.setId(20);
user.setName("new name");
user.setAge(88);
user.setCreateTime(new Date());

LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyEntity(user);
.executeSumResult();
// 返回 result 为 1
使用 Map 作为数据容器
Map<String, Object> user = new HashMap<>();
newValue.put("id", 20);
newValue.put("name", "new name");
newValue.put("age", 88);
newValue.put("create_time", new Date());

LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyMap(user);
.executeSumResult();
// 返回 result 为 1

批量化

当有大量数据需要插入时可以选择使用批量化写入。

User user1 = new User();
...
User user2 = new User();
...
User user3 = new User();
...

LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyEntity(user1, user2, user3); // 不定参方式
//.applyEntity(new User[]{user1, user2, user3}); // 使用数组
//.applyEntity(Arrays.asList(user1, user2, user3));// 使用 List
.executeSumResult();
// 返回 result 为 3
  • 对于 Map 结构可以使用 applyMap 方法替代 applyEntity。
  • 在通过 executeSumResult 方法正式写入数据之前,applyEntity、applyMap 两个方法可以被多次调用以适应不同批次数据的设置。

写入冲突

向数据库插入重复数据通常并非有意而为之,而一旦出现主键冲突就会比较麻烦。一般的解决办法是先查询在选择更新或者是写入。

常规方法
if (adapter.queryByEntity(User.class)
.eq(User::getId,user.getId())
.queryForCount() > 0) {
// 更新
} else {
// 写入
}

好消息是数据库本身对于写入冲突多半提供了更加高效的方式,比如:

  • MySQL 数据库可以使用 ON DUPLICATE KEY UPDATE 字句修饰 INSERT。
  • Oracle 数据库可以使用 MERGE INTO ... WHEN MATCHED THEN ... WHEN NOT MATCHED THEN ... 语句。

使用这些数据库特性需要有 2 个先决条件。

  • 需要 dbVisitor 的数据库方言能够支持,了解数据库支持性
  • 需要通过 onDuplicateStrategy 方法指定冲突处理策略。

dbVisitor 中对于这种情况可以配置冲突策略,这样就可以避免在写入数据时多余的代码逻辑。可选的冲突策略有三个:

  • 报错(Into),使用常规的 INSERT INTO 写入数据。
  • 替换(Update),使用 Merge 或者 ON CONFLICT 等数据库特定语言来实现数据写入冲突是自动更新。
  • 忽略(Ignore),使用 Ignore 或者其它数据库提供的专用语句来实现写入错误时忽略报错。

默认策略(INTO)

默认策略下将会使用普通的 insert into 语句进行数据插入,当遇到数据冲突通常数据库会报错。

默认策略可以不指定,也可以明确设置
LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyEntity(user);
.onDuplicateStrategy(DuplicateKeyStrategy.Into) // 明确设置
.executeSumResult();

替换策略(UPDATE)

替换策略的实现是根据具体数据库方言实现决定,如:

  • 对于 MySQL 将会使用 ON DUPLICATE KEY UPDATE 子句修饰 INSERT。
  • 对于 Oracle 将会使用 MERGE INTO ... WHEN MATCHED THEN ... WHEN NOT MATCHED THEN ... 语句。
  • 对于 PostgreSql 将会使用 ON CONFLICT (...) DO UPDATE SET ... 子句修饰 INSERT。
提示

该策略是否支持需要以数据库方言为准,如果数据库方言不支持此类语句强行指定会报错。

使用方式
LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyEntity(user);
.onDuplicateStrategy(DuplicateKeyStrategy.Update) // 冲突更新
.executeSumResult();

忽略策略(IGNORE)

替换策略的实现是根据具体数据库方言实现决定,如:

  • 对于 MySQL 将会使用 INSERT IGNORE 语句。
  • 对于 Oracle 将会使用 MERGE INTO ... WHEN NOT MATCHED THEN ... 语句。
  • 对于 达梦数据库将会使用数据库 HINT IGNORE_ROW_ON_DUPKEY_INDEX 根据主键列进行忽略。
使用方式
LambdaTemplate lambda = ...
int result = lambda.insert(User.class)
.applyEntity(user);
.onDuplicateStrategy(DuplicateKeyStrategy.Ignore) // 冲突忽略
.executeSumResult();