add upsert

This commit is contained in:
Looly 2022-01-14 19:41:55 +08:00
parent 27e5f58692
commit b63dbe7a9a
6 changed files with 31 additions and 32 deletions

View File

@ -10,7 +10,8 @@
* 【core 】 增加KetamaHashissue#2084@Github * 【core 】 增加KetamaHashissue#2084@Github
* 【crypto 】 增加SignUtil * 【crypto 】 增加SignUtil
* 【json 】 JSONGetter增加getBeanList方法 * 【json 】 JSONGetter增加getBeanList方法
* 【core 】 ObjectUtil 添加三个defaultIfXxxx方法用于节省CPU及内存损耗。(pr#2094@Github) * 【core 】 ObjectUtil 添加三个defaultIfXxxx方法用于节省CPU及内存损耗(pr#2094@Github)
* 【db 】 增加单条数据原生upsert语义支持(pr#501@Gitee)
* *
### 🐞Bug修复 ### 🐞Bug修复
* 【core 】 修复setter重载导致匹配错误issue#2082@Github * 【core 】 修复setter重载导致匹配错误issue#2082@Github

View File

@ -96,6 +96,7 @@ public class DialectRunner implements Serializable {
* @param keys 需要检查唯一性的字段 * @param keys 需要检查唯一性的字段
* @return 插入行数 * @return 插入行数
* @throws SQLException SQL执行异常 * @throws SQLException SQL执行异常
* @since 5.7.20
*/ */
public int upsert(Connection conn, Entity record, String... keys) throws SQLException { public int upsert(Connection conn, Entity record, String... keys) throws SQLException {
PreparedStatement ps = getDialect().psForUpsert(conn, record, keys); PreparedStatement ps = getDialect().psForUpsert(conn, record, keys);
@ -106,12 +107,26 @@ public class DialectRunner implements Serializable {
DbUtil.close(ps); DbUtil.close(ps);
} }
} else { } else {
final Entity where = record.filter(keys); return insertOrUpdate(conn, record, keys);
if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) { }
return update(conn, record, where); }
} else {
return insert(conn, record).length; /**
} * 插入或更新数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int insertOrUpdate(Connection conn, Entity record, String... keys) throws SQLException {
final Entity where = record.filter(keys);
if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) {
return update(conn, record, where);
} else {
return insert(conn, record)[0];
} }
} }

View File

@ -1,7 +1,6 @@
package cn.hutool.db; package cn.hutool.db;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.db.dialect.Dialect; import cn.hutool.db.dialect.Dialect;
import cn.hutool.db.dialect.DialectFactory; import cn.hutool.db.dialect.DialectFactory;
import cn.hutool.db.handler.EntityListHandler; import cn.hutool.db.handler.EntityListHandler;
@ -15,7 +14,6 @@ import cn.hutool.db.sql.SqlUtil;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -23,7 +21,8 @@ import java.util.List;
/** /**
* SQL执行类<br> * SQL执行类<br>
* 此执行类只接受方言参数不需要数据源只有在执行方法时需要数据库连接对象<br> * 此执行类只接受方言参数不需要数据源只有在执行方法时需要数据库连接对象<br>
* 此对象存在的意义在于可以由使用者自定义数据库连接对象并执行多个方法方便事务的统一控制或减少连接对象的创建关闭 * 此对象存在的意义在于可以由使用者自定义数据库连接对象并执行多个方法方便事务的统一控制或减少连接对象的创建关闭<br>
* 相比{@link DialectRunner}此类中提供了更多重载方法
* *
* @author Luxiaolei * @author Luxiaolei
*/ */
@ -83,25 +82,6 @@ public class SqlConnRunner extends DialectRunner {
//---------------------------------------------------------------------------- CRUD start //---------------------------------------------------------------------------- CRUD start
/**
* 插入或更新数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @param keys 需要检查唯一性的字段
* @return 插入行数
* @throws SQLException SQL执行异常
*/
public int insertOrUpdate(Connection conn, Entity record, String... keys) throws SQLException {
final Entity where = record.filter(keys);
if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) {
return update(conn, record, where);
} else {
return insert(conn, record);
}
}
/** /**
* 批量插入数据<br> * 批量插入数据<br>
* 需要注意的是批量插入每一条数据结构必须一致批量插入数据时会获取第一条数据的字段结构之后的数据会按照这个格式插入<br> * 需要注意的是批量插入每一条数据结构必须一致批量插入数据时会获取第一条数据的字段结构之后的数据会按照这个格式插入<br>

View File

@ -144,13 +144,15 @@ public interface Dialect extends Serializable {
} }
/** /**
* 构建用于upsert的PreparedStatement * 构建用于upsert的PreparedStatement<br>
* 方言实现需实现此默认方法默认返回{@code null}
* *
* @param conn 数据库连接对象 * @param conn 数据库连接对象
* @param entity 数据实体类包含表名 * @param entity 数据实体类包含表名
* @param keys 查找字段 * @param keys 查找字段
* @return PreparedStatement * @return PreparedStatement
* @throws SQLException SQL执行异常 * @throws SQLException SQL执行异常
* @since 5.7.20
*/ */
default PreparedStatement psForUpsert(Connection conn, Entity entity, String... keys) throws SQLException { default PreparedStatement psForUpsert(Connection conn, Entity entity, String... keys) throws SQLException {
return null; return null;

View File

@ -310,7 +310,6 @@ public class SqlBuilder implements Builder<String> {
if (null != wrapper) { if (null != wrapper) {
// 包装表名 // 包装表名
// entity = wrapper.wrap(entity);
entity.setTableName(wrapper.wrap(entity.getTableName())); entity.setTableName(wrapper.wrap(entity.getTableName()));
} }

View File

@ -7,6 +7,7 @@ import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Entity; import cn.hutool.db.Entity;
import java.io.Serializable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -17,7 +18,8 @@ import java.util.Map.Entry;
* @author Looly * @author Looly
* *
*/ */
public class Wrapper { public class Wrapper implements Serializable {
private static final long serialVersionUID = 1L;
/** 前置包装符号 */ /** 前置包装符号 */
private Character preWrapQuote; private Character preWrapQuote;