diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ddb22fb..0fef330cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ * 【core 】 增加KetamaHash(issue#2084@Github) * 【crypto 】 增加SignUtil * 【json 】 JSONGetter增加getBeanList方法 -* 【core 】 ObjectUtil 添加三个defaultIfXxxx方法,用于节省CPU及内存损耗。(pr#2094@Github) +* 【core 】 ObjectUtil 添加三个defaultIfXxxx方法,用于节省CPU及内存损耗(pr#2094@Github) +* 【db 】 增加单条数据原生upsert语义支持(pr#501@Gitee) * ### 🐞Bug修复 * 【core 】 修复setter重载导致匹配错误(issue#2082@Github) diff --git a/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java b/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java index b1003b987..26e18bc09 100644 --- a/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java +++ b/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java @@ -96,6 +96,7 @@ public class DialectRunner implements Serializable { * @param keys 需要检查唯一性的字段 * @return 插入行数 * @throws SQLException SQL执行异常 + * @since 5.7.20 */ public int upsert(Connection conn, Entity record, String... keys) throws SQLException { PreparedStatement ps = getDialect().psForUpsert(conn, record, keys); @@ -106,12 +107,26 @@ public class DialectRunner implements Serializable { DbUtil.close(ps); } } else { - final Entity where = record.filter(keys); - if (MapUtil.isNotEmpty(where) && count(conn, where) > 0) { - return update(conn, record, where); - } else { - return insert(conn, record).length; - } + return insertOrUpdate(conn, record, keys); + } + } + + /** + * 插入或更新数据
+ * 此方法不会关闭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]; } } diff --git a/hutool-db/src/main/java/cn/hutool/db/SqlConnRunner.java b/hutool-db/src/main/java/cn/hutool/db/SqlConnRunner.java index 95290d6db..28f1bfc2b 100644 --- a/hutool-db/src/main/java/cn/hutool/db/SqlConnRunner.java +++ b/hutool-db/src/main/java/cn/hutool/db/SqlConnRunner.java @@ -1,7 +1,6 @@ package cn.hutool.db; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.db.dialect.Dialect; import cn.hutool.db.dialect.DialectFactory; import cn.hutool.db.handler.EntityListHandler; @@ -15,7 +14,6 @@ import cn.hutool.db.sql.SqlUtil; import javax.sql.DataSource; import java.sql.Connection; -import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Collection; import java.util.List; @@ -23,7 +21,8 @@ import java.util.List; /** * SQL执行类
* 此执行类只接受方言参数,不需要数据源,只有在执行方法时需要数据库连接对象
- * 此对象存在的意义在于,可以由使用者自定义数据库连接对象,并执行多个方法,方便事务的统一控制或减少连接对象的创建关闭 + * 此对象存在的意义在于,可以由使用者自定义数据库连接对象,并执行多个方法,方便事务的统一控制或减少连接对象的创建关闭
+ * 相比{@link DialectRunner},此类中提供了更多重载方法 * * @author Luxiaolei */ @@ -83,25 +82,6 @@ public class SqlConnRunner extends DialectRunner { //---------------------------------------------------------------------------- CRUD start - /** - * 插入或更新数据
- * 此方法不会关闭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); - } - } - /** * 批量插入数据
* 需要注意的是,批量插入每一条数据结构必须一致。批量插入数据时会获取第一条数据的字段结构,之后的数据会按照这个格式插入。
diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java b/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java index 16058bc4c..d37a7e867 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/Dialect.java @@ -144,13 +144,15 @@ public interface Dialect extends Serializable { } /** - * 构建用于upsert的PreparedStatement + * 构建用于upsert的PreparedStatement
+ * 方言实现需实现此默认方法,默认返回{@code null} * * @param conn 数据库连接对象 * @param entity 数据实体类(包含表名) * @param keys 查找字段 * @return PreparedStatement * @throws SQLException SQL执行异常 + * @since 5.7.20 */ default PreparedStatement psForUpsert(Connection conn, Entity entity, String... keys) throws SQLException { return null; diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java index ac666054b..fcf09c671 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlBuilder.java @@ -310,7 +310,6 @@ public class SqlBuilder implements Builder { if (null != wrapper) { // 包装表名 - // entity = wrapper.wrap(entity); entity.setTableName(wrapper.wrap(entity.getTableName())); } diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/Wrapper.java b/hutool-db/src/main/java/cn/hutool/db/sql/Wrapper.java index fd823804e..12ee7778d 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/Wrapper.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/Wrapper.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.db.Entity; +import java.io.Serializable; import java.util.Arrays; import java.util.Collection; import java.util.Map.Entry; @@ -17,7 +18,8 @@ import java.util.Map.Entry; * @author Looly * */ -public class Wrapper { +public class Wrapper implements Serializable { + private static final long serialVersionUID = 1L; /** 前置包装符号 */ private Character preWrapQuote;