From 59cc3e7e6a934484c85e94129bff2bfe10e48889 Mon Sep 17 00:00:00 2001 From: aunix Date: Thu, 24 Oct 2024 10:45:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/mybatis/mapper/BaseMapper.java | 11 ++++++++ .../java/io/mybatis/mapper/fn/FnProvider.java | 21 ++++++++++++++++ .../mybatis/mapper/fn/UserFnMapperTest.java | 25 +++++++++++++++++++ .../io/mybatis/service/AbstractService.java | 7 ++++++ .../io/mybatis/service/EntityService.java | 9 +++++++ .../java/io/mybatis/service/ServiceTest.java | 22 ++++++++++++++++ 6 files changed, 95 insertions(+) diff --git a/mapper/src/main/java/io/mybatis/mapper/BaseMapper.java b/mapper/src/main/java/io/mybatis/mapper/BaseMapper.java index 8dc774a..d94300f 100644 --- a/mapper/src/main/java/io/mybatis/mapper/BaseMapper.java +++ b/mapper/src/main/java/io/mybatis/mapper/BaseMapper.java @@ -62,6 +62,17 @@ default ExampleWrapper wrapper() { @UpdateProvider(type = FnProvider.class, method = "updateByPrimaryKeySelectiveWithForceFields") int updateByPrimaryKeySelectiveWithForceFields(@Param("entity") S entity, @Param("fns") Fn.Fns forceUpdateFields); + /** + * 根据主键更新指定的字段 + * + * @param entity 实体类型 + * @param updateFields 指定更新的字段 + * @return 1成功,0失败 + */ + @Lang(Caching.class) + @UpdateProvider(type = FnProvider.class, method = "updateForFieldListByPrimaryKey") + int updateForFieldListByPrimaryKey(@Param("entity") S entity, @Param("fns") Fn.Fns updateFields); + /** * 根据指定字段集合查询:field in (fieldValueList) *

diff --git a/mapper/src/main/java/io/mybatis/mapper/fn/FnProvider.java b/mapper/src/main/java/io/mybatis/mapper/fn/FnProvider.java index 4a7642c..730bf72 100644 --- a/mapper/src/main/java/io/mybatis/mapper/fn/FnProvider.java +++ b/mapper/src/main/java/io/mybatis/mapper/fn/FnProvider.java @@ -52,6 +52,27 @@ public String getSql(EntityTable entity) { }); } + /** + * 根据主键更新指定的字段 + * + * @param providerContext 上下文 + * @return cacheKey + */ + public static String updateForFieldListByPrimaryKey(ProviderContext providerContext) { + return SqlScript.caching(providerContext, new SqlScript() { + @Override + public String getSql(EntityTable entity) { + return "UPDATE " + entity.tableName() + + set(() -> + entity.updateColumns().stream().map(column -> + choose(() -> + whenTest("fns != null and fns.fieldNames().contains('" + column.property() + "')", () -> column.columnEqualsProperty("entity.") + ",")) + ).collect(Collectors.joining(LF))) + + where(() -> entity.idColumns().stream().map(column -> column.columnEqualsProperty("entity.")).collect(Collectors.joining(" AND "))); + } + }); + } + /** * 根据实体字段条件查询唯一的实体,根据实体字段条件批量查询,查询结果的数量由方法定义 * diff --git a/mapper/src/test/java/io/mybatis/mapper/fn/UserFnMapperTest.java b/mapper/src/test/java/io/mybatis/mapper/fn/UserFnMapperTest.java index 88b89b7..5eb15a6 100644 --- a/mapper/src/test/java/io/mybatis/mapper/fn/UserFnMapperTest.java +++ b/mapper/src/test/java/io/mybatis/mapper/fn/UserFnMapperTest.java @@ -46,6 +46,31 @@ public void testUpdateByPrimaryKeySelectiveWithForceFields() { } } + @Test + public void testUpdateForFieldListByPrimaryKey() { + SqlSession sqlSession = getSqlSession(); + try { + // 元数据(1, '张无忌', '男', 1) + UserMapper mapper = sqlSession.getMapper(UserMapper.class); + User user = mapper.selectByPrimaryKey(1L).get(); + user.setUserName("test"); + user.setSex("女"); + user.setStatus(false); + int count = mapper.updateForFieldListByPrimaryKey(user, Fn.of(User::getUserName, User::getStatus)); + Assert.assertEquals(1, count); + user = mapper.selectByPrimaryKey(1L).get(); + // 断言 sex 不会被更新 + Assert.assertEquals("男", user.getSex()); + // 断言userName被成功更新 + Assert.assertEquals("test", user.getUserName()); + // 短信 status不会被更新,user status 为不允许更新字段, 所以这里不会更新 + Assert.assertEquals(user.getStatus(), true); + } finally { + //不要忘记关闭sqlSession + sqlSession.close(); + } + } + @Test public void testSelectColumnsOne() { SqlSession sqlSession = getSqlSession(); diff --git a/service/src/main/java/io/mybatis/service/AbstractService.java b/service/src/main/java/io/mybatis/service/AbstractService.java index 366e938..4886dfb 100644 --- a/service/src/main/java/io/mybatis/service/AbstractService.java +++ b/service/src/main/java/io/mybatis/service/AbstractService.java @@ -84,6 +84,13 @@ public T update(T entity) { return entity; } + @Override + public T update(T entity, Fn... updateFields) { + Assert.isTrue(baseMapper.updateForFieldListByPrimaryKey( + entity, Fn.of(updateFields)) == 1, UPDATE_FAILURE); + return entity; + } + @Override public T updateSelective(T entity) { Assert.isTrue(baseMapper.updateByPrimaryKeySelective(entity) == 1, UPDATE_FAILURE); diff --git a/service/src/main/java/io/mybatis/service/EntityService.java b/service/src/main/java/io/mybatis/service/EntityService.java index 2caf7c9..f7d18df 100644 --- a/service/src/main/java/io/mybatis/service/EntityService.java +++ b/service/src/main/java/io/mybatis/service/EntityService.java @@ -55,6 +55,15 @@ public interface EntityService { */ T update(T entity); + /** + * 更新(指定字段) + * + * @param entity 实体类 + * @param updateFields 需要更新的字段 + * @return 返回更新成功后的实体,远程服务调用时,由于序列化和反序列化,入参和返回值不是同一个对象 + */ + T update(T entity, Fn... updateFields); + /** * 更新(非空字段) * diff --git a/service/src/test/java/io/mybatis/service/ServiceTest.java b/service/src/test/java/io/mybatis/service/ServiceTest.java index fe39ac6..6b9acea 100644 --- a/service/src/test/java/io/mybatis/service/ServiceTest.java +++ b/service/src/test/java/io/mybatis/service/ServiceTest.java @@ -182,6 +182,28 @@ public void testUserService() { Assert.assertTrue(userService.findOne(user) != null); } + @Test + public void testUpdate() { + // 元数据 (1, 'admin', 1) + UserService userService = context.getBean(UserService.class); + User user = userService.findById(1); + Assert.assertNotNull(user); + + user.setName("administrator"); + user.setRoleId(11); + userService.update(user, User::getName); + user = userService.findById(1); + Assert.assertEquals("administrator", user.getName()); + Assert.assertEquals(1, (int) user.getRoleId()); + + user.setName("admin"); + user.setRoleId(11); + userService.update(user, User::getRoleId); + user = userService.findById(1); + Assert.assertEquals("administrator", user.getName()); + Assert.assertEquals(11, (int) user.getRoleId()); + } + @Test public void testIssues50() { UserService userService = context.getBean(UserService.class);