diff --git a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/Column.java b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/Column.java index f006aaa8..7f7f1d27 100644 --- a/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/Column.java +++ b/mybatis-flex-annotation/src/main/java/com/mybatisflex/annotation/Column.java @@ -54,7 +54,7 @@ public @interface Column { boolean isLogicDelete() default false; /** - * 是否为乐观锁字段,如果是的话更新的时候会去检测当前版本号,更新成功的话会设置当前版本号 +1 + * 是否为乐观锁字段,若是乐观锁字段的话,数据更新的时候会去检测当前版本号,若更新成功的话会设置当前版本号 +1 * 只能用于数值的字段 */ boolean version() default false; diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java index daa3343d..f92be604 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/CommonsDialectImpl.java @@ -528,6 +528,12 @@ public class CommonsDialectImpl implements IDialect { onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + " = " + value)); } + //乐观锁字段 + String versionColumn = tableInfo.getVersionColumn(); + if (StringUtil.isNotBlank(versionColumn)) { + stringJoiner.add(wrap(versionColumn) + " = " + wrap(versionColumn) + " + 1 "); + } + sql.append(stringJoiner); sql.append(" WHERE "); @@ -538,11 +544,19 @@ public class CommonsDialectImpl implements IDialect { sql.append(wrap(primaryKeys[i])).append(" = ?"); } + //逻辑删除条件,已删除的数据不能被修改 String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); if (StringUtil.isNotBlank(logicDeleteColumn)) { sql.append(" AND ").append(wrap(logicDeleteColumn)).append(" = 0 "); } + //乐观锁条件 + if (StringUtil.isNotBlank(versionColumn)) { + Object versionValue = tableInfo.getColumnValue(entity, versionColumn); + sql.append(" AND ").append(wrap(versionColumn)).append(" = ").append(versionValue); + } + + return sql.toString(); } @@ -553,23 +567,41 @@ public class CommonsDialectImpl implements IDialect { Set modifyAttrs = tableInfo.obtainUpdateColumns(entity, ignoreNulls, true); sql.append("UPDATE ").append(wrap(tableInfo.getTableName())).append(" SET "); - int index = 0; + + StringJoiner stringJoiner = new StringJoiner(", "); + for (String modifyAttr : modifyAttrs) { - if (index > 0) { - sql.append(", "); - } - sql.append(wrap(modifyAttr)).append(" = ? "); - index++; + stringJoiner.add(wrap(modifyAttr) + " = ?"); } Map onUpdateColumns = tableInfo.getOnUpdateColumns(); if (onUpdateColumns != null && !onUpdateColumns.isEmpty()) { - StringJoiner stringJoiner = new StringJoiner(", "); onUpdateColumns.forEach((column, value) -> stringJoiner.add(wrap(column) + " = " + value)); - sql.append(", ").append(stringJoiner); } + //乐观锁字段 + String versionColumn = tableInfo.getVersionColumn(); + if (StringUtil.isNotBlank(versionColumn)) { + stringJoiner.add(wrap(versionColumn) + " = " + wrap(versionColumn) + " + 1 "); + } + + sql.append(stringJoiner); + + sql.append(" WHERE "); + + //乐观锁条件 + if (StringUtil.isNotBlank(versionColumn)) { + Object versionValue = tableInfo.getColumnValue(entity, versionColumn); + queryWrapper.and(new StringQueryCondition(wrap(versionColumn) + " = " + versionValue)); + } + + //逻辑删除条件,已删除的数据不能被修改 + String logicDeleteColumn = tableInfo.getLogicDeleteColumn(); + if (StringUtil.isNotBlank(logicDeleteColumn)) { + queryWrapper.and(new StringQueryCondition(wrap(logicDeleteColumn) + " = 0")); + } + sql.append(buildWhereConditionSql(queryWrapper)); return sql.toString(); diff --git a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java index 1afb850c..2009fa5b 100644 --- a/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java +++ b/mybatis-flex-core/src/main/java/com/mybatisflex/core/provider/EntitySqlProvider.java @@ -58,6 +58,9 @@ public class EntitySqlProvider { TableInfo tableInfo = ProviderUtil.getTableInfo(context); + //设置乐观锁版本字段的初始化 + tableInfo.initVersionValueIfNecessary(entity); + Object[] values = tableInfo.obtainInsertValues(entity); ProviderUtil.setSqlArgs(params, values); @@ -81,6 +84,10 @@ public class EntitySqlProvider { } TableInfo tableInfo = ProviderUtil.getTableInfo(context); + for (Object entity : entities) { + tableInfo.initVersionValueIfNecessary(entity); + } + Object[] values = new Object[0]; for (Object entity : entities) { values = ArrayUtil.concat(values, tableInfo.obtainInsertValues(entity)); 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 9b6c15cf..0d9d239d 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 @@ -22,6 +22,7 @@ import com.mybatisflex.core.row.Row; import com.mybatisflex.core.util.ArrayUtil; import com.mybatisflex.core.util.ClassUtil; import com.mybatisflex.core.util.CollectionUtil; +import com.mybatisflex.core.util.StringUtil; import org.apache.ibatis.mapping.ResultFlag; import org.apache.ibatis.mapping.ResultMap; import org.apache.ibatis.mapping.ResultMapping; @@ -285,7 +286,12 @@ public class TableInfo { } for (String property : properties) { String column = getColumnByProperty(property); - if (onUpdateColumns != null && onUpdateColumns.containsKey(column)){ + if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { + continue; + } + + //过滤乐观锁字段 + if (Objects.equals(column, versionColumn)) { continue; } @@ -302,7 +308,12 @@ public class TableInfo { //not ModifyAttrsRecord else { for (String column : this.columns) { - if (onUpdateColumns != null && onUpdateColumns.containsKey(column)){ + if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { + continue; + } + + //过滤乐观锁字段 + if (Objects.equals(column, versionColumn)) { continue; } @@ -343,7 +354,11 @@ public class TableInfo { } for (String property : properties) { String column = getColumnByProperty(property); - if (onUpdateColumns != null && onUpdateColumns.containsKey(column)){ + if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { + continue; + } + //过滤乐观锁字段 + if (Objects.equals(column, versionColumn)) { continue; } @@ -360,7 +375,12 @@ public class TableInfo { // normal entity. not ModifyAttrsRecord else { for (String column : this.columns) { - if (onUpdateColumns != null && onUpdateColumns.containsKey(column)){ + if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { + continue; + } + + //过滤乐观锁字段 + if (Objects.equals(column, versionColumn)) { continue; } @@ -433,6 +453,11 @@ public class TableInfo { return getPropertyValue(metaObject, columnPropertyMapping.get(column)); } + public Object getColumnValue(Object entityObject, String column) { + MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); + return getPropertyValue(metaObject, columnPropertyMapping.get(column)); + } + private Object getPropertyValue(MetaObject metaObject, String property) { if (property != null && metaObject.hasGetter(property)) { @@ -463,4 +488,21 @@ public class TableInfo { } return (T) instance; } + + /** + * 初始化乐观锁版本号 + * + * @param entityObject + */ + public void initVersionValueIfNecessary(Object entityObject) { + if (StringUtil.isBlank(versionColumn)) { + return; + } + + MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); + Object columnValue = getColumnValue(entityObject, versionColumn); + if (columnValue == null) { + metaObject.setValue(columnPropertyMapping.get(versionColumn), 0); + } + } }