From b06cf1843fa1a5c0734634251030b7bd3da8fa5d Mon Sep 17 00:00:00 2001 From: "jin.huang" Date: Thu, 2 Apr 2020 19:41:48 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=E5=A2=9E=E5=8A=A0=E6=89=B9=E9=87=8Fup?= =?UTF-8?q?date=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...BatchUpdatePropertyByPrimaryKeyMapper.java | 31 +++++ ...tchUpdatePropertyByPrimaryKeyProvider.java | 109 ++++++++++++++++++ .../additional/update/batch/FieldValue.java | 42 +++++++ .../BatchUpdatePropertyByPrimaryKeyTest.java | 93 +++++++++++++++ .../update/batch/CountryMapper.java | 7 ++ .../update/batch/mybatis-config.xml | 51 ++++++++ 6 files changed, 333 insertions(+) create mode 100644 extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyMapper.java create mode 100644 extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java create mode 100644 extra/src/main/java/tk/mybatis/mapper/additional/update/batch/FieldValue.java create mode 100644 extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java create mode 100644 extra/src/test/java/tk/mybatis/mapper/additional/update/batch/CountryMapper.java create mode 100644 extra/src/test/java/tk/mybatis/mapper/additional/update/batch/mybatis-config.xml diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyMapper.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyMapper.java new file mode 100644 index 000000000..a5885e664 --- /dev/null +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyMapper.java @@ -0,0 +1,31 @@ +package tk.mybatis.mapper.additional.update.batch; + +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.UpdateProvider; +import tk.mybatis.mapper.annotation.RegisterMapper; +import tk.mybatis.mapper.weekend.Fn; + +import java.util.List; + +@RegisterMapper +public interface BatchUpdatePropertyByPrimaryKeyMapper { + + /** + * 多条数据更新同一字段为相同值 + * @param fn 字段名 + * @param value 更新的字段值 + * @param primaryKeys 数据主键集合 + * @return + */ + @UpdateProvider(type = BatchUpdatePropertyByPrimaryKeyProvider.class, method = "dynamicSQL") + int batchUpdateFieldByIdList(@Param("fn") Fn fn, @Param("value") Object value, @Param("idList") List primaryKeys); + + /** + * 多条数据更新多个字段为相同值 + * @param fieldValues 更新字段及更新值 + * @param primaryKeys 数据主键集合 + * @return + */ + @UpdateProvider(type = BatchUpdatePropertyByPrimaryKeyProvider.class, method = "dynamicSQL") + int batchUpdateFieldListByIdList(@Param("fieldList") List> fieldValues, @Param("idList") List primaryKeys); +} diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java new file mode 100644 index 000000000..1d0cf366e --- /dev/null +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java @@ -0,0 +1,109 @@ +package tk.mybatis.mapper.additional.update.batch; + +import org.apache.ibatis.logging.Log; +import org.apache.ibatis.logging.LogFactory; +import org.apache.ibatis.mapping.MappedStatement; +import tk.mybatis.mapper.MapperException; +import tk.mybatis.mapper.entity.EntityColumn; +import tk.mybatis.mapper.entity.EntityTable; +import tk.mybatis.mapper.mapperhelper.EntityHelper; +import tk.mybatis.mapper.mapperhelper.MapperHelper; +import tk.mybatis.mapper.mapperhelper.MapperTemplate; +import tk.mybatis.mapper.mapperhelper.SqlHelper; + +import java.util.Set; + +public class BatchUpdatePropertyByPrimaryKeyProvider extends MapperTemplate { + + private static final Log log = LogFactory.getLog(BatchUpdatePropertyByPrimaryKeyProvider.class); + + public BatchUpdatePropertyByPrimaryKeyProvider(Class mapperClass, MapperHelper mapperHelper) { + super(mapperClass, mapperHelper); + } + + public String batchUpdateFieldByIdList(MappedStatement ms) { + Class entityClass = getEntityClass(ms); + StringBuilder sql = new StringBuilder(); + sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); + // set + appendSet(sql, entityClass); + // where + appendWhereIdList(sql, entityClass, true); + return sql.toString(); + } + + public String batchUpdateFieldListByIdList(MappedStatement ms) { + Class entityClass = getEntityClass(ms); + StringBuilder sql = new StringBuilder(); + sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); + // set + appendFileListSet(sql, entityClass); + // where + appendWhereIdList(sql, entityClass, true); + return sql.toString(); + } + + private void appendSet(StringBuilder sql, Class entityClass) { + sql.append(""); + //通过实体类名获取运行时属性对应的字段 + String ognl = new StringBuilder("${@") + .append(getProviderName()) + .append("@getColumnByProperty(@java.lang.Class@forName(\"") + .append(entityClass.getName()) + .append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(fn))}").toString(); + sql.append(ognl + " = #{value}\n"); + sql.append(""); + } + + private void appendWhereIdList(StringBuilder sql, Class entityClass, boolean useVersion) { + Set columnList = EntityHelper.getPKColumns(entityClass); + if (columnList.size() == 1) { + EntityColumn column = columnList.iterator().next(); + sql.append(""); + sql.append(""); + sql.append("#{id}"); + sql.append(""); + if (useVersion) { + sql.append(SqlHelper.whereVersion(entityClass)); + } + sql.append(""); + } else { + throw new MapperException("继承 ByIdList 方法的实体类[" + entityClass.getCanonicalName() + "]中必须只有一个带有 @Id 注解的字段"); + } + } + + private void appendFileListSet(StringBuilder sql, Class entityClass) { + sql.append(""); + sql.append(""); + //通过实体类名获取运行时属性对应的字段 + String ognl = "${@" + + getProviderName() + + "@getColumnByProperty(@java.lang.Class@forName(\"" + + entityClass.getName() + + "\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(field.fn))}"; + sql.append(ognl + " = #{field.value}\n"); + sql.append(""); + sql.append(""); + + } + + private String getProviderName() { + return BatchUpdatePropertyByPrimaryKeyProvider.class.getName(); + } + + /** + * 根据实体Class和属性名获取对应的表字段名 + * + * @param entityClass 实体Class对象 + * @param property 属性名 + * @return + */ + public static String getColumnByProperty(Class entityClass, String property) { + EntityTable entityTable = EntityHelper.getEntityTable(entityClass); + EntityColumn entityColumn = entityTable.getPropertyMap().get(property); + return entityColumn.getColumn(); + } +} diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/FieldValue.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/FieldValue.java new file mode 100644 index 000000000..d89d25ffb --- /dev/null +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/FieldValue.java @@ -0,0 +1,42 @@ +package tk.mybatis.mapper.additional.update.batch; + +import tk.mybatis.mapper.weekend.Fn; + +public class FieldValue { + + /** + * 字段名 + * 形式必须是 类::方法 + * e.g. Country::getCountryname + */ + private Fn fn; + + /** + * 更新的字段值 + */ + private Object value; + + public FieldValue(Fn fn, Object value) { + this.fn = fn; + this.value = value; + } + + public FieldValue() { + } + + public Fn getFn() { + return fn; + } + + public void setFn(Fn fn) { + this.fn = fn; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } +} diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java new file mode 100644 index 000000000..894249fc9 --- /dev/null +++ b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java @@ -0,0 +1,93 @@ +package tk.mybatis.mapper.additional.update.batch; + +import org.apache.ibatis.session.SqlSession; +import org.junit.Assert; +import org.junit.Test; +import tk.mybatis.mapper.additional.BaseTest; +import tk.mybatis.mapper.additional.Country; + +import java.io.IOException; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author goldhuang + * @Description: 验证批量更新 + * @date 2020-04-02 + */ +public class BatchUpdatePropertyByPrimaryKeyTest extends BaseTest { + + /** + * 获取 mybatis 配置 + * + * @return + */ + protected Reader getConfigFileAsReader() throws IOException { + URL url = getClass().getResource("mybatis-config.xml"); + return toReader(url); + } + + ; + + @Test + public void testBatchUpdateFieldByIdList() { + SqlSession sqlSession = getSqlSession(); + try { + tk.mybatis.mapper.additional.update.batch.CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); + + //(1, 'Angola', 'AO', 1) + Country old1 = mapper.selectByPrimaryKey(1L); + //(2, 'Afghanistan', 'AF', 1) + Country old2 = mapper.selectByPrimaryKey(2L); + + int updateCount = mapper.batchUpdateFieldByIdList(Country::getCountryname, "Gold", Arrays.asList(old1.getId(), old2.getId())); + Assert.assertEquals(2, updateCount); + + old1 = mapper.selectByPrimaryKey(1L); + old2 = mapper.selectByPrimaryKey(2L); + + Assert.assertEquals(1L, old1.getId().longValue()); + Assert.assertEquals(2L, old2.getId().longValue()); + Assert.assertEquals("Gold", old1.getCountryname()); + Assert.assertEquals("Gold", old2.getCountryname()); + } finally { + sqlSession.close(); + } + } + + @Test + public void batchUpdateFieldListByIdList() { + SqlSession sqlSession = getSqlSession(); + try { + tk.mybatis.mapper.additional.update.batch.CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); + + //(1, 'Angola', 'AO', 1) + Country old1 = mapper.selectByPrimaryKey(1L); + //(2, 'Afghanistan', 'AF', 1) + Country old2 = mapper.selectByPrimaryKey(2L); + + List> fieldValues = new ArrayList<>(); + fieldValues.add(new FieldValue<>(Country::getCountrycode, "GD")); + fieldValues.add(new FieldValue<>(Country::getCountryname, "Gold")); + + int updateCount = mapper.batchUpdateFieldListByIdList(fieldValues, Arrays.asList(old1.getId(), old2.getId())); + Assert.assertEquals(2, updateCount); + + old1 = mapper.selectByPrimaryKey(1L); + old2 = mapper.selectByPrimaryKey(2L); + + Assert.assertEquals(1L, old1.getId().longValue()); + Assert.assertEquals(2L, old2.getId().longValue()); + Assert.assertEquals("Gold", old1.getCountryname()); + Assert.assertEquals("Gold", old2.getCountryname()); + Assert.assertEquals("GD", old1.getCountrycode()); + Assert.assertEquals("GD", old2.getCountrycode()); + } finally { + sqlSession.close(); + } + } + +} diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/CountryMapper.java b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/CountryMapper.java new file mode 100644 index 000000000..a68680546 --- /dev/null +++ b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/CountryMapper.java @@ -0,0 +1,7 @@ +package tk.mybatis.mapper.additional.update.batch; + +import tk.mybatis.mapper.additional.Country; +import tk.mybatis.mapper.common.BaseMapper; + +public interface CountryMapper extends BaseMapper, BatchUpdatePropertyByPrimaryKeyMapper { +} diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/mybatis-config.xml b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/mybatis-config.xml new file mode 100644 index 000000000..a7367185f --- /dev/null +++ b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/mybatis-config.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From f24eba7d472c9e2963bf739db73e055db1f79760 Mon Sep 17 00:00:00 2001 From: "jin.huang" Date: Wed, 8 Apr 2020 10:57:44 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=E6=B7=BB=E5=8A=A0=E4=B8=BB=E9=94=AELis?= =?UTF-8?q?t=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...BatchUpdatePropertyByPrimaryKeyProvider.java | 17 +++++++++++++++++ .../BatchUpdatePropertyByPrimaryKeyTest.java | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java index 1d0cf366e..a7f11769d 100644 --- a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java @@ -11,6 +11,7 @@ import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; +import java.util.List; import java.util.Set; public class BatchUpdatePropertyByPrimaryKeyProvider extends MapperTemplate { @@ -59,6 +60,8 @@ private void appendWhereIdList(StringBuilder sql, Class entityClass, boolean Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = columnList.iterator().next(); + sql.append(""); sql.append(""); sql.append(" entityClass, String property) EntityColumn entityColumn = entityTable.getPropertyMap().get(property); return entityColumn.getColumn(); } + + /** + * 保证 idList 不能为空 + * + * @param list + * @param errorMsg + */ + public static void notEmpty(List list, String errorMsg){ + if(list == null || list.size() == 0){ + throw new MapperException(errorMsg); + } + } + + } diff --git a/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java index 894249fc9..547082c99 100644 --- a/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java +++ b/extra/src/test/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyTest.java @@ -58,6 +58,17 @@ public void testBatchUpdateFieldByIdList() { } } + @Test(expected = Exception.class) + public void testBatchUpdateFieldByEmptyIdList() { + SqlSession sqlSession = getSqlSession(); + try { + tk.mybatis.mapper.additional.update.batch.CountryMapper mapper = sqlSession.getMapper(CountryMapper.class); + mapper.batchUpdateFieldByIdList(Country::getCountryname, "Gold", new ArrayList<>()); + } finally { + sqlSession.close(); + } + } + @Test public void batchUpdateFieldListByIdList() { SqlSession sqlSession = getSqlSession(); From 93ce1c1664d5573586ea28da14b9ddb2c5bf7d7f Mon Sep 17 00:00:00 2001 From: "jin.huang" Date: Wed, 8 Apr 2020 10:59:50 +0800 Subject: [PATCH 3/5] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java index a7f11769d..4b9b2ac6c 100644 --- a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java @@ -74,7 +74,7 @@ private void appendWhereIdList(StringBuilder sql, Class entityClass, boolean } sql.append(""); } else { - throw new MapperException("继承 ByIdList 方法的实体类[" + entityClass.getCanonicalName() + "]中必须只有一个带有 @Id 注解的字段"); + throw new MapperException("继承 BatchUpdatePropertyByPrimaryKeyMapper 方法的实体类[" + entityClass.getCanonicalName() + "]中必须只有一个带有 @Id 注解的字段"); } } From b8f192cdb1816498239f2382fdb48678fce16dd1 Mon Sep 17 00:00:00 2001 From: "jin.huang" Date: Wed, 8 Apr 2020 11:02:08 +0800 Subject: [PATCH 4/5] =?UTF-8?q?fix:=E7=B1=BB=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java index 4b9b2ac6c..0b15a41d2 100644 --- a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java @@ -60,7 +60,7 @@ private void appendWhereIdList(StringBuilder sql, Class entityClass, boolean Set columnList = EntityHelper.getPKColumns(entityClass); if (columnList.size() == 1) { EntityColumn column = columnList.iterator().next(); - sql.append(""); sql.append(""); sql.append(" Date: Mon, 13 Apr 2020 17:34:25 +0800 Subject: [PATCH 5/5] fix:optimization --- .../batch/BatchUpdatePropertyByPrimaryKeyProvider.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java index 0b15a41d2..67481ca4d 100644 --- a/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java +++ b/extra/src/main/java/tk/mybatis/mapper/additional/update/batch/BatchUpdatePropertyByPrimaryKeyProvider.java @@ -1,7 +1,5 @@ package tk.mybatis.mapper.additional.update.batch; -import org.apache.ibatis.logging.Log; -import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.MapperException; import tk.mybatis.mapper.entity.EntityColumn; @@ -16,8 +14,6 @@ public class BatchUpdatePropertyByPrimaryKeyProvider extends MapperTemplate { - private static final Log log = LogFactory.getLog(BatchUpdatePropertyByPrimaryKeyProvider.class); - public BatchUpdatePropertyByPrimaryKeyProvider(Class mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } @@ -26,9 +22,7 @@ public String batchUpdateFieldByIdList(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); - // set appendSet(sql, entityClass); - // where appendWhereIdList(sql, entityClass, true); return sql.toString(); } @@ -37,9 +31,7 @@ public String batchUpdateFieldListByIdList(MappedStatement ms) { Class entityClass = getEntityClass(ms); StringBuilder sql = new StringBuilder(); sql.append(SqlHelper.updateTable(entityClass, tableName(entityClass))); - // set appendFileListSet(sql, entityClass); - // where appendWhereIdList(sql, entityClass, true); return sql.toString(); }