From e7fc09922bbbeed585d9ce2bdd144fb8d1879fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=80=E6=BA=90=E6=B5=B7=E5=93=A5?= Date: Mon, 3 Jul 2023 17:20:24 +0800 Subject: [PATCH] feat: add UpdateWrapper --- .../core/dialect/impl/CommonsDialectImpl.java | 57 ++++++-- .../core/dialect/impl/OracleDialect.java | 3 +- .../core/javassist/ModifyAttrsRecord.java | 52 ------- .../core/provider/RowSqlProvider.java | 4 +- .../java/com/mybatisflex/core/row/Row.java | 130 +++++++++--------- .../java/com/mybatisflex/core/row/RowCPI.java | 21 ++- .../com/mybatisflex/core/table/TableInfo.java | 88 ++++++++++-- .../ModifyAttrsRecordHandler.java | 25 ++-- .../ModifyAttrsRecordProxyFactory.java | 4 +- .../com/mybatisflex/core/update/RawValue.java | 48 +++++++ .../core/update/UpdateWrapper.java | 82 +++++++++++ .../{javassist => update}/package-info.java | 2 +- .../mybatisflex/core/util/UpdateEntity.java | 2 +- .../com/mybatisflex/test/DbTestStarter.java | 10 +- .../test/MapperProxyCacheTestStarter.java | 1 + 15 files changed, 359 insertions(+), 170 deletions(-) delete mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecord.java rename mybatis-flex-core/src/main/java/com/mybatisflex/core/{javassist => update}/ModifyAttrsRecordHandler.java (64%) rename mybatis-flex-core/src/main/java/com/mybatisflex/core/{javassist => update}/ModifyAttrsRecordProxyFactory.java (94%) create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/update/RawValue.java create mode 100644 mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateWrapper.java rename mybatis-flex-core/src/main/java/com/mybatisflex/core/{javassist => update}/package-info.java (94%) diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java index 59de94ce..07149605 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/CommonsDialectImpl.java @@ -24,6 +24,7 @@ import com.mybatisflex.core.query.*; import com.mybatisflex.core.row.Row; import com.mybatisflex.core.row.RowCPI; import com.mybatisflex.core.table.TableInfo; +import com.mybatisflex.core.update.RawValue; import com.mybatisflex.core.util.ArrayUtil; import com.mybatisflex.core.util.CollectionUtil; import com.mybatisflex.core.util.StringUtil; @@ -71,12 +72,12 @@ public class CommonsDialectImpl implements IDialect { StringBuilder fields = new StringBuilder(); StringBuilder questions = new StringBuilder(); - Set attrs = row.obtainModifyAttrs(); + Set modifyAttrs = RowCPI.getModifyAttrs(row); int index = 0; - for (String attr : attrs) { + for (String attr : modifyAttrs) { fields.append(wrap(attr)); questions.append(PLACEHOLDER); - if (index != attrs.size() - 1) { + if (index != modifyAttrs.size() - 1) { fields.append(DELIMITER); questions.append(DELIMITER); } @@ -100,7 +101,7 @@ public class CommonsDialectImpl implements IDialect { StringBuilder questions = new StringBuilder(); Row firstRow = rows.get(0); - Set attrs = firstRow.obtainModifyAttrs(); + Set attrs = RowCPI.getModifyAttrs(firstRow); int index = 0; for (String column : attrs) { fields.append(wrap(column)); @@ -198,7 +199,8 @@ public class CommonsDialectImpl implements IDialect { public String forUpdateById(String schema, String tableName, Row row) { StringBuilder sql = new StringBuilder(); - Set modifyAttrs = row.obtainModifyAttrs(); + Set modifyAttrs = RowCPI.getModifyAttrs(row); + Map rawValueMap = RowCPI.getRawValueMap(row); String[] primaryKeys = RowCPI.obtainsPrimaryKeyStrings(row); sql.append(UPDATE); @@ -213,7 +215,14 @@ public class CommonsDialectImpl implements IDialect { if (index > 0) { sql.append(DELIMITER); } - sql.append(wrap(colName)).append(EQUALS_PLACEHOLDER); + sql.append(wrap(colName)); + + if (rawValueMap.containsKey(colName)) { + sql.append(EQUALS).append(rawValueMap.get(colName).toSql(this)); + } else { + sql.append(EQUALS_PLACEHOLDER); + } + index++; } } @@ -232,7 +241,8 @@ public class CommonsDialectImpl implements IDialect { public String forUpdateByQuery(QueryWrapper queryWrapper, Row row) { StringBuilder sql = new StringBuilder(); - Set modifyAttrs = row.obtainModifyAttrs(); + Set modifyAttrs = RowCPI.getModifyAttrs(row); + Map rawValueMap = RowCPI.getRawValueMap(row); List queryTables = CPI.getQueryTables(queryWrapper); if (queryTables == null || queryTables.size() != 1) { @@ -247,7 +257,15 @@ public class CommonsDialectImpl implements IDialect { if (index > 0) { sql.append(DELIMITER); } - sql.append(wrap(modifyAttr)).append(EQUALS_PLACEHOLDER); + + sql.append(wrap(modifyAttr)); + + if (rawValueMap.containsKey(modifyAttr)) { + sql.append(EQUALS).append(rawValueMap.get(modifyAttr).toSql(this)); + } else { + sql.append(EQUALS_PLACEHOLDER); + } + index++; } @@ -690,15 +708,20 @@ public class CommonsDialectImpl implements IDialect { public String forUpdateEntity(TableInfo tableInfo, Object entity, boolean ignoreNulls) { StringBuilder sql = new StringBuilder(); - Set modifyAttrs = tableInfo.obtainUpdateColumns(entity, ignoreNulls, false); + Set updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, false); + Map rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); String[] primaryKeys = tableInfo.getPrimaryKeys(); sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this)).append(SET); StringJoiner stringJoiner = new StringJoiner(DELIMITER); - for (String modifyAttr : modifyAttrs) { - stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); + for (String modifyAttr : updateColumns) { + if (rawValueMap.containsKey(modifyAttr)) { + stringJoiner.add(wrap(modifyAttr)).add(EQUALS).add(rawValueMap.get(modifyAttr).toSql(this)); + } else { + stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); + } } Map onUpdateColumns = tableInfo.getOnUpdateColumns(); @@ -756,17 +779,23 @@ public class CommonsDialectImpl implements IDialect { public String forUpdateEntityByQuery(TableInfo tableInfo, Object entity, boolean ignoreNulls, QueryWrapper queryWrapper) { StringBuilder sql = new StringBuilder(); - Set modifyAttrs = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true); + Set updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true); + Map rawValueMap = tableInfo.obtainUpdateRawValueMap(entity); sql.append(UPDATE).append(forHint(CPI.getHint(queryWrapper))) .append(tableInfo.getWrapSchemaAndTableName(this)).append(SET); StringJoiner stringJoiner = new StringJoiner(DELIMITER); - for (String modifyAttr : modifyAttrs) { - stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); + for (String modifyAttr : updateColumns) { + if (rawValueMap.containsKey(modifyAttr)) { + stringJoiner.add(wrap(modifyAttr)).add(EQUALS).add(rawValueMap.get(modifyAttr).toSql(this)); + } else { + stringJoiner.add(wrap(modifyAttr) + EQUALS_PLACEHOLDER); + } } + Map onUpdateColumns = tableInfo.getOnUpdateColumns(); if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + EQUALS + value)); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java index bfb9a4b7..83f8de9e 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/impl/OracleDialect.java @@ -19,6 +19,7 @@ import com.mybatisflex.core.constant.SqlConsts; import com.mybatisflex.core.dialect.KeywordWrap; import com.mybatisflex.core.dialect.LimitOffsetProcessor; import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.row.RowCPI; import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.util.CollectionUtil; import com.mybatisflex.core.util.StringUtil; @@ -150,7 +151,7 @@ public class OracleDialect extends CommonsDialectImpl { */ StringBuilder fields = new StringBuilder(); Row firstRow = rows.get(0); - Set attrs = firstRow.obtainModifyAttrs(); + Set attrs = RowCPI.getModifyAttrs(firstRow); int index = 0; for (String column : attrs) { fields.append(wrap(column)); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecord.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecord.java deleted file mode 100644 index f289f8cf..00000000 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecord.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * http://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.mybatisflex.core.javassist; - -import org.apache.ibatis.javassist.util.proxy.ProxyObject; - -import java.io.Serializable; -import java.util.Set; - -public interface ModifyAttrsRecord extends Serializable { - - /** - * 注意: - * 对于 entity 来说,这里存放的只是 属性的名称,而非字段 - * 对于 row 来说,存放的则是 字段 名称 - */ - default Set getModifyAttrs(){ - ModifyAttrsRecordHandler handler = (ModifyAttrsRecordHandler) ((ProxyObject) this).getHandler(); - return handler.getModifyAttrs(); - } - - default void addModifyAttr(String attr) { - getModifyAttrs().add(attr); - } - - default void removeModifyAttr(String attr) { - getModifyAttrs().remove(attr); - } - - default Set obtainModifyAttrs() { - return getModifyAttrs(); - } - - default void clearModifyFlag() { - getModifyAttrs().clear(); - } - - -} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/RowSqlProvider.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/RowSqlProvider.java index 10ac72e2..b3dd9431 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/RowSqlProvider.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/RowSqlProvider.java @@ -87,8 +87,8 @@ public class RowSqlProvider { // 让所有 row 的列顺序和值的数量与第条数据保持一致 // 这个必须 new 一个 LinkedHashSet,因为 keepModifyAttrs 会清除 row 所有的 modifyAttrs - Set modifyAttrs = new LinkedHashSet<>(rows.get(0).obtainModifyAttrs()); - rows.forEach(row -> row.prepareAttrs(modifyAttrs)); + Set modifyAttrs = new LinkedHashSet<>(RowCPI.getModifyAttrs(rows.get(0))); + rows.forEach(row -> RowCPI.resetByAttrs(row, modifyAttrs)); Object[] values = new Object[]{}; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java index 1f46699e..0227bd6a 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/Row.java @@ -16,8 +16,11 @@ package com.mybatisflex.core.row; import com.mybatisflex.core.FlexConsts; -import com.mybatisflex.core.javassist.ModifyAttrsRecord; import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.query.QueryCondition; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.update.RawValue; +import com.mybatisflex.core.update.UpdateWrapper; import com.mybatisflex.core.util.ArrayUtil; import com.mybatisflex.core.util.ConvertUtil; import com.mybatisflex.core.util.SqlUtil; @@ -30,7 +33,7 @@ import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.*; -public class Row extends LinkedHashMap implements ModifyAttrsRecord { +public class Row extends LinkedHashMap implements UpdateWrapper { //主键,多个主键用英文逗号隔开 private RowKey[] primaryKeys; @@ -40,15 +43,11 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec return row.set(key, value); } - - private final Set modifyAttrs = new LinkedHashSet<>(); - @Override - public Set getModifyAttrs() { - return modifyAttrs; + public Map getUpdates() { + return this; } - public static Row ofKey(String primaryKey, Object value) { Row row = new Row(); String[] primaryKeyStrings = primaryKey.split(","); @@ -98,6 +97,7 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec } + @Override public Row set(String column, Object value) { if (StringUtil.isBlank(column)) { throw new IllegalArgumentException("key column not be null or empty."); @@ -105,28 +105,23 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec SqlUtil.keepColumnSafely(column); - //覆盖 put - super.put(column, value); - - boolean isPrimaryKey = false; - if (this.primaryKeys != null) { - for (RowKey rowKey : primaryKeys) { - if (rowKey.getKeyColumn().equals(column)) { - isPrimaryKey = true; - break; - } - } - } - - if (!isPrimaryKey) { - addModifyAttr(column); + if (value instanceof QueryWrapper || value instanceof QueryCondition) { + setRaw(column, value); + } else { + super.put(column, value); } return this; } + @Override public Row set(QueryColumn queryColumn, Object value) { - return set(queryColumn.getName(), value); + if (value instanceof QueryWrapper || value instanceof QueryCondition) { + seRaw(queryColumn, value); + } else { + super.put(queryColumn.getName(), value); + } + return this; } @@ -287,7 +282,6 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec @Override public Object remove(Object key) { - removeModifyAttr(key.toString()); return super.remove(key); } @@ -315,57 +309,54 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec return ret; } - public void prepareAttrsByKeySet(){ - this.modifyAttrs.clear(); - this.modifyAttrs.addAll(keySet()); - - if (this.primaryKeys != null){ - for (RowKey primaryKey : primaryKeys) { - this.modifyAttrs.removeIf(s -> s.equalsIgnoreCase(primaryKey.getKeyColumn())); - } - } - } - - - public void prepareAttrsByKeySet(RowKey ... primaryKeys){ - this.modifyAttrs.clear(); - this.modifyAttrs.addAll(keySet()); - this.primaryKeys = primaryKeys; - - for (RowKey primaryKey : primaryKeys) { - this.modifyAttrs.removeIf(s -> s.equalsIgnoreCase(primaryKey.getKeyColumn())); - } - } - - public void prepareAttrs(Collection attrs) { - if (attrs == null) { - throw new NullPointerException("attrs is null."); - } - clearModifyFlag(); - modifyAttrs.addAll(attrs); - } - public RowKey[] getPrimaryKeys() { return primaryKeys; } public void setPrimaryKeys(RowKey... primaryKeys) { this.primaryKeys = primaryKeys; - for (RowKey primaryKey : primaryKeys) { - this.modifyAttrs.removeIf(s -> s.equalsIgnoreCase(primaryKey.getKeyColumn())); + } + + Set getModifyAttrs() { + int pkCount = primaryKeys != null ? primaryKeys.length : 0; + if (pkCount == 0) { + return keySet(); } + + Set attrs = new LinkedHashSet<>(keySet()); + attrs.removeIf(this::isPk); + return attrs; + } + + Map getRawValueMap(){ + Map map = new HashMap<>(); + forEach((s, o) -> { + if (o instanceof RawValue){ + map.put(s, (RawValue) o); + } + }); + return map; + } + + + + + void resetByAttrs(Set resetAttrs) { + keySet().removeIf(s -> !resetAttrs.contains(s)); } /** * 获取修改的值,值需要保持顺序,返回的内容不包含主键的值 */ - Object[] obtainModifyValues() { - Object[] values = new Object[modifyAttrs.size()]; - int index = 0; - for (String modifyAttr : modifyAttrs) { - values[index++] = get(modifyAttr); + Object[] obtainModifyValuesWithoutPk() { + List values = new ArrayList<>(); + for (String key : keySet()) { + Object value = get(key); + if (!isPk(key) && !(value instanceof RawValue)) { + values.add(value); + } } - return values; + return values.toArray(); } @@ -396,9 +387,20 @@ public class Row extends LinkedHashMap implements ModifyAttrsRec Object[] obtainAllModifyValues() { - return ArrayUtil.concat(obtainModifyValues(), obtainsPrimaryValues()); + return ArrayUtil.concat(obtainModifyValuesWithoutPk(), obtainsPrimaryValues()); } + private boolean isPk(String attr) { + if (primaryKeys != null && primaryKeys.length > 0) { + for (RowKey primaryKey : primaryKeys) { + if (primaryKey.keyColumn.equalsIgnoreCase(attr)) { + return true; + } + } + } + return false; + } + } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowCPI.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowCPI.java index 257f5f39..6eaca963 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowCPI.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/row/RowCPI.java @@ -15,15 +15,21 @@ */ package com.mybatisflex.core.row; +import com.mybatisflex.core.update.RawValue; + +import java.util.Map; +import java.util.Set; + /** * cross package invoker */ public class RowCPI { - private RowCPI() {} + private RowCPI() { + } public static Object[] obtainModifyValues(Row row) { - return row.obtainModifyValues(); + return row.obtainModifyValuesWithoutPk(); } public static String[] obtainsPrimaryKeyStrings(Row row) { @@ -42,4 +48,15 @@ public class RowCPI { return row.obtainAllModifyValues(); } + public static Set getModifyAttrs(Row row) { + return row.getModifyAttrs(); + } + + public static Map getRawValueMap(Row row){ + return row.getRawValueMap(); + } + public static void resetByAttrs(Row row, Set resetAttrs) { + row.resetByAttrs(resetAttrs); + } + } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java index 2ffa13fb..2f0172d6 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/table/TableInfo.java @@ -21,12 +21,13 @@ import com.mybatisflex.core.FlexGlobalConfig; import com.mybatisflex.core.constant.SqlConsts; import com.mybatisflex.core.dialect.IDialect; import com.mybatisflex.core.exception.FlexExceptions; -import com.mybatisflex.core.javassist.ModifyAttrsRecord; import com.mybatisflex.core.logicdelete.LogicDeleteManager; import com.mybatisflex.core.mybatis.TypeHandlerObject; import com.mybatisflex.core.query.*; import com.mybatisflex.core.row.Row; import com.mybatisflex.core.tenant.TenantManager; +import com.mybatisflex.core.update.RawValue; +import com.mybatisflex.core.update.UpdateWrapper; import com.mybatisflex.core.util.*; import org.apache.ibatis.mapping.ResultFlag; import org.apache.ibatis.mapping.ResultMap; @@ -298,7 +299,8 @@ public class TableInfo { } public String getColumnByProperty(String property) { - return propertyColumnMapping.get(property); + String column = propertyColumnMapping.get(property); + return StringUtil.isNotBlank(column) ? column : property; } public Map> getAssociationType() { @@ -479,6 +481,28 @@ public class TableInfo { } } + + public Map obtainUpdateRawValueMap(Object entity) { + if (!(entity instanceof UpdateWrapper)) { + return Collections.emptyMap(); + } + + Map updates = ((UpdateWrapper) entity).getUpdates(); + if (updates.isEmpty()) { + return Collections.emptyMap(); + } + + Map map = new HashMap<>(); + updates.forEach((key, value) -> { + if (value instanceof RawValue) { + String column = getColumnByProperty(key); + map.put(column, (RawValue) value); + } + }); + + return map; + } + /** * 获取要修改的值 * @@ -488,13 +512,14 @@ public class TableInfo { public Set obtainUpdateColumns(Object entity, boolean ignoreNulls, boolean includePrimary) { MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); Set columns = new LinkedHashSet<>(); //需使用 LinkedHashSet 保证 columns 的顺序 - if (entity instanceof ModifyAttrsRecord) { - Set properties = ((ModifyAttrsRecord) entity).obtainModifyAttrs(); - if (properties.isEmpty()) { + if (entity instanceof UpdateWrapper) { +// Set properties = ((UpdateWrapper) entity).getModifyAttrs(); + Map updates = ((UpdateWrapper) entity).getUpdates(); + if (updates.isEmpty()) { return Collections.emptySet(); } - for (String property : properties) { - String column = propertyColumnMapping.get(property); + for (String property : updates.keySet()) { + String column = getColumnByProperty(property); if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { continue; } @@ -508,6 +533,7 @@ public class TableInfo { continue; } +// Object value = updates.get(property); // ModifyAttrsRecord 忽略 ignoreNulls 的设置 // Object value = getPropertyValue(metaObject, property); // if (ignoreNulls && value == null) { @@ -557,15 +583,19 @@ public class TableInfo { * @return 数组 */ public Object[] buildUpdateSqlArgs(Object entity, boolean ignoreNulls, boolean includePrimary) { - MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); + List values = new ArrayList<>(); - if (entity instanceof ModifyAttrsRecord) { - Set properties = ((ModifyAttrsRecord) entity).obtainModifyAttrs(); - if (properties.isEmpty()) { - return values.toArray(); + if (entity instanceof UpdateWrapper) { + Map updates = ((UpdateWrapper) entity).getUpdates(); + if (updates.isEmpty()) { + return FlexConsts.EMPTY_ARRAY; } - for (String property : properties) { - String column = propertyColumnMapping.get(property); +// Set properties = (Set) updates; +// if (properties.isEmpty()) { +// return values.toArray(); +// } + for (String property : updates.keySet()) { + String column = getColumnByProperty(property); if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { continue; } @@ -578,7 +608,19 @@ public class TableInfo { continue; } - Object value = buildColumnSqlArg(metaObject, column); + Object value = updates.get(property); + if (value instanceof RawValue) { + continue; + } + + if (value != null) { + ColumnInfo columnInfo = columnInfoMapping.get(column); + TypeHandler typeHandler = columnInfo.buildTypeHandler(); + if (typeHandler != null) { + value = new TypeHandlerObject(typeHandler, value, columnInfo.getJdbcType()); + } + } + // ModifyAttrsRecord 忽略 ignoreNulls 的设置, // 当使用 ModifyAttrsRecord 时,可以理解为要对字段进行 null 值进行更新,否则没必要使用 ModifyAttrsRecord // if (ignoreNulls && value == null) { @@ -589,6 +631,8 @@ public class TableInfo { } // normal entity. not ModifyAttrsRecord else { + MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); + for (String column : this.columns) { if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { continue; @@ -915,6 +959,20 @@ public class TableInfo { } +// private Object buildColumnSqlArg(Object value, String column) { +// ColumnInfo columnInfo = columnInfoMapping.get(column); +//// Object value = getPropertyValue(metaObject, columnInfo.property); +// +// if (value != null) { +// TypeHandler typeHandler = columnInfo.buildTypeHandler(); +// if (typeHandler != null) { +// return new TypeHandlerObject(typeHandler, value, columnInfo.getJdbcType()); +// } +// } +// +// return value; +// } + private Object buildColumnSqlArg(MetaObject metaObject, String column) { ColumnInfo columnInfo = columnInfoMapping.get(column); Object value = getPropertyValue(metaObject, columnInfo.property); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordHandler.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordHandler.java similarity index 64% rename from mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordHandler.java rename to mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordHandler.java index 953c7dba..c7b19635 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordHandler.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordHandler.java @@ -13,39 +13,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mybatisflex.core.javassist; +package com.mybatisflex.core.update; import com.mybatisflex.core.util.StringUtil; import org.apache.ibatis.javassist.util.proxy.MethodHandler; import java.lang.reflect.Method; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.LinkedHashMap; +import java.util.Map; +class ModifyAttrsRecordHandler implements MethodHandler { -public class ModifyAttrsRecordHandler implements MethodHandler { + //更新内容 + private final Map updates = new LinkedHashMap<>(); - private final Set modifyAttrs = new LinkedHashSet<>(); - - public Set getModifyAttrs() { - return modifyAttrs; + public Map getUpdates() { + return updates; } @Override public Object invoke(Object self, Method originalMethod, Method proxyMethod, Object[] args) throws Throwable { - if (originalMethod.getName().startsWith("set")){ + String methodName = originalMethod.getName(); + if (methodName.startsWith("set") + && methodName.length() > 3 + && Character.isUpperCase(methodName.charAt(3)) + && originalMethod.getParameterCount() == 1) { String property = StringUtil.firstCharToLowerCase(originalMethod.getName().substring(3)); - modifyAttrs.add(property); + updates.put(property, args[0]); } return proxyMethod.invoke(self, args); } - } diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordProxyFactory.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordProxyFactory.java similarity index 94% rename from mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordProxyFactory.java rename to mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordProxyFactory.java index 4e5d175f..8a1d2674 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/ModifyAttrsRecordProxyFactory.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/ModifyAttrsRecordProxyFactory.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mybatisflex.core.javassist; +package com.mybatisflex.core.update; import org.apache.ibatis.javassist.util.proxy.ProxyFactory; import org.apache.ibatis.javassist.util.proxy.ProxyObject; @@ -37,7 +37,7 @@ public class ModifyAttrsRecordProxyFactory { factory.setSuperclass(target); Class[] interfaces = Arrays.copyOf(target.getInterfaces(), target.getInterfaces().length + 1); - interfaces[interfaces.length - 1] = ModifyAttrsRecord.class; + interfaces[interfaces.length - 1] = UpdateWrapper.class; factory.setInterfaces(interfaces); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/RawValue.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/RawValue.java new file mode 100644 index 00000000..4570e26c --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/RawValue.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mybatisflex.core.update; + +import com.mybatisflex.core.dialect.IDialect; +import com.mybatisflex.core.query.QueryCondition; +import com.mybatisflex.core.query.QueryWrapper; + +import java.io.Serializable; + +public class RawValue implements Serializable { + + private Object object; + + public RawValue(Object object) { + this.object = object; + } + + + public String toSql(IDialect dialect) { + if (object instanceof String) { + return (String) object; + } + + if (object instanceof QueryWrapper) { + return dialect.buildSelectSql((QueryWrapper) object); + } + + if (object instanceof QueryCondition) { + return ((QueryCondition) object).toSql(null, dialect); + } + + return object.toString(); + } +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateWrapper.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateWrapper.java new file mode 100644 index 00000000..295a1d63 --- /dev/null +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/UpdateWrapper.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mybatisflex.core.update; + +import com.mybatisflex.core.query.QueryColumn; +import com.mybatisflex.core.query.QueryCondition; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.util.LambdaGetter; +import com.mybatisflex.core.util.LambdaUtil; +import org.apache.ibatis.javassist.util.proxy.ProxyObject; + +import java.io.Serializable; +import java.util.Map; + +public interface UpdateWrapper extends Serializable { + + default Map getUpdates() { + ModifyAttrsRecordHandler handler = (ModifyAttrsRecordHandler) ((ProxyObject) this).getHandler(); + return handler.getUpdates(); + } + + + default UpdateWrapper set(String property, Object value) { + if (value instanceof QueryWrapper || value instanceof QueryCondition) { + setRaw(property, value); + } else { + getUpdates().put(property, value); + } + return this; + } + + + default UpdateWrapper set(LambdaGetter getter, Object value) { + if (value instanceof QueryWrapper || value instanceof QueryCondition) { + seRaw(getter, value); + } else { + getUpdates().put(LambdaUtil.getFieldName(getter), value); + } + + return this; + } + + + default UpdateWrapper set(QueryColumn queryColumn, Object value) { + if (value instanceof QueryWrapper || value instanceof QueryCondition) { + seRaw(queryColumn, value); + } else { + getUpdates().put(queryColumn.getName(), value); + } + return this; + } + + default UpdateWrapper setRaw(String property, Object value) { + getUpdates().put(property, new RawValue(value)); + return this; + } + + + default UpdateWrapper seRaw(LambdaGetter getter, Object value) { + getUpdates().put(LambdaUtil.getFieldName(getter), new RawValue(value)); + return this; + } + + default UpdateWrapper seRaw(QueryColumn queryColumn, Object value) { + getUpdates().put(queryColumn.getName(), new RawValue(value)); + return this; + } + +} diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/package-info.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/package-info.java similarity index 94% rename from mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/package-info.java rename to mybatis-flex-core/src/main/java/com/mybatisflex/core/update/package-info.java index 0fafa3c2..9291fdc3 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/javassist/package-info.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/update/package-info.java @@ -17,4 +17,4 @@ /** * 处理部分字段更新。 */ -package com.mybatisflex.core.javassist; \ No newline at end of file +package com.mybatisflex.core.update; \ No newline at end of file diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/UpdateEntity.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/UpdateEntity.java index ece89e72..4ccaa9d0 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/UpdateEntity.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/util/UpdateEntity.java @@ -15,7 +15,7 @@ */ package com.mybatisflex.core.util; -import com.mybatisflex.core.javassist.ModifyAttrsRecordProxyFactory; +import com.mybatisflex.core.update.ModifyAttrsRecordProxyFactory; import com.mybatisflex.core.table.IdInfo; import com.mybatisflex.core.table.TableInfo; import com.mybatisflex.core.table.TableInfoFactory; diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/DbTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/DbTestStarter.java index cc931115..da844803 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/DbTestStarter.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/DbTestStarter.java @@ -92,11 +92,11 @@ public class DbTestStarter { // } // rows.forEach(row2 -> row2.setPrimaryKeys(RowKey.AUTO)); - rows.forEach(r -> { - r.prepareAttrsByKeySet(); - r.setPrimaryKeys(RowKey.AUTO); - }); - Db.insertBatch(null,"tb_account", rows, 100); +// rows.forEach(r -> { +// r.prepareAttrsByKeySet(); +// r.setPrimaryKeys(RowKey.AUTO); +// }); +// Db.insertBatch(null,"tb_account", rows, 100); //再次查询全部数据 rows = Db.selectAll(null,"tb_account"); diff --git a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/MapperProxyCacheTestStarter.java b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/MapperProxyCacheTestStarter.java index 0401c4ec..be2798af 100644 --- a/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/MapperProxyCacheTestStarter.java +++ b/mybatis-flex-test/mybatis-flex-native-test/src/main/java/com/mybatisflex/test/MapperProxyCacheTestStarter.java @@ -44,6 +44,7 @@ public class MapperProxyCacheTestStarter { .addMapper(AccountMapper.class) .start(); + //开启审计功能 AuditManager.setAuditEnable(true);