瀏覽代碼

fix: #1386(github) 逻辑删除字段为Date类型并且非删除数据日期为null

yuxiaobin 6 年之前
父節點
當前提交
246b1ec861

+ 37 - 16
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -15,28 +15,34 @@
  */
 package com.baomidou.mybatisplus.core.metadata;
 
+import static java.util.stream.Collectors.joining;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+import org.apache.ibatis.mapping.ResultFlag;
+import org.apache.ibatis.mapping.ResultMap;
+import org.apache.ibatis.mapping.ResultMapping;
+import org.apache.ibatis.session.Configuration;
+
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
-import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
+
 import lombok.AccessLevel;
 import lombok.Data;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
-import org.apache.ibatis.mapping.ResultFlag;
-import org.apache.ibatis.mapping.ResultMap;
-import org.apache.ibatis.mapping.ResultMapping;
-import org.apache.ibatis.session.Configuration;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Predicate;
-
-import static java.util.stream.Collectors.joining;
 
 /**
  * 数据库表反射信息
@@ -331,9 +337,7 @@ public class TableInfo implements Constants {
         if (logicDelete) {
             TableFieldInfo field = fieldList.stream().filter(TableFieldInfo::isLogicDelete).findFirst()
                 .orElseThrow(() -> ExceptionUtils.mpe("can't find the logicFiled from table {%s}", tableName));
-            String formatStr = field.isCharSequence() ? "'%s'" : "%s";
-            String logicDeleteSql = field.getColumn() + EQUALS +
-                String.format(formatStr, deleteValue ? field.getLogicDeleteValue() : field.getLogicNotDeleteValue());
+            String logicDeleteSql = formatLogicDeleteSql(field, deleteValue);
             if (startWithAnd) {
                 logicDeleteSql = " AND " + logicDeleteSql;
             }
@@ -342,6 +346,23 @@ public class TableInfo implements Constants {
         return EMPTY;
     }
 
+    /**
+     * format logic delete SQL, can be overrided by subclass
+     * github #1386
+     *
+     * @param field       TableFieldInfo
+     * @param deleteValue true: logicDeleteValue, false: logicNotDeleteValue
+     * @return
+     */
+    protected String formatLogicDeleteSql(TableFieldInfo field, boolean deleteValue) {
+        String value = deleteValue ? field.getLogicDeleteValue() : field.getLogicNotDeleteValue();
+        if (NULL.equalsIgnoreCase(value)) {
+            return field.getColumn() + " is NULL";
+        } else {
+            return field.getColumn() + EQUALS + String.format(field.isCharSequence() ? "'%s'" : "%s", value);
+        }
+    }
+
     /**
      * 自动构建 resultMap 并注入(如果条件符合的话)
      */

+ 26 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/BaseTest.java

@@ -15,15 +15,41 @@
  */
 package com.baomidou.mybatisplus.test.h2;
 
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.test.annotation.DirtiesContext;
 
+import com.baomidou.mybatisplus.test.h2.entity.H2User;
+import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
+
 @DirtiesContext
 public class BaseTest {
 
+    @Resource
+    protected JdbcTemplate jdbcTemplate;
+
     protected static final String NQQ = "聂秋秋";
 
     protected void log(Object object) {
         System.out.println(object);
     }
 
+    protected List<H2User> queryByName(String name) {
+        String sql = "select TEST_ID, NAME, AGE,LAST_UPDATED_DT from h2user ";
+        if (name != null) {
+            sql += "where name='" + name + "'";
+        }
+        return jdbcTemplate.query(sql, (rs, rowNum) -> {
+            H2User u = new H2User();
+            u.setTestId(rs.getLong("TEST_ID"));
+            u.setName(rs.getString("NAME"));
+            u.setAge(AgeEnum.parseValue(rs.getInt("AGE")));
+            u.setLastUpdatedDt(rs.getDate("LAST_UPDATED_DT"));
+            return u;
+        });
+    }
+
 }

+ 16 - 8
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2Delete1Eq1Test.java

@@ -15,12 +15,11 @@
  */
 package com.baomidou.mybatisplus.test.h2;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
-import com.baomidou.mybatisplus.test.h2.mapper.H2StudentMapper;
-import com.baomidou.mybatisplus.test.h2.mapper.H2UserMapper;
-import com.baomidou.mybatisplus.test.h2.entity.H2Student;
-import com.baomidou.mybatisplus.test.h2.entity.H2User;
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.MethodOrderer;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
@@ -29,7 +28,12 @@ import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
-import javax.annotation.Resource;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.test.h2.entity.H2Student;
+import com.baomidou.mybatisplus.test.h2.entity.H2User;
+import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
+import com.baomidou.mybatisplus.test.h2.mapper.H2StudentMapper;
+import com.baomidou.mybatisplus.test.h2.mapper.H2UserMapper;
 
 /**
  * Mybatis Plus H2 Junit Test
@@ -64,7 +68,7 @@ class H2Delete1Eq1Test extends BaseTest {
         for (long i = 0; i < 10L; i++) {
             defaultMapper.insert(new H2Student(i, "Tom长大了", 1));
         }
-        log(logicDeleteMapper.selectList(new QueryWrapper<>(h2User).eq("name","2").orderByAsc("name")));
+        log(logicDeleteMapper.selectList(new QueryWrapper<>(h2User).eq("name", "2").orderByAsc("name")));
         log(defaultMapper.selectList(new QueryWrapper<H2Student>().orderByAsc("id")));
         log(defaultMapper.selectOne(new QueryWrapper<H2Student>().last("limit 1")));
 
@@ -79,5 +83,9 @@ class H2Delete1Eq1Test extends BaseTest {
     void delete() {
         logicDeleteMapper.delete(new QueryWrapper<>());
         defaultMapper.delete(new QueryWrapper<>());
+        Assertions.assertEquals(0, (int) logicDeleteMapper.selectCount(new QueryWrapper<>()));
+        List<H2User> userList = queryByName(null);
+        System.out.println(userList.size());
+        Assertions.assertNotEquals(0, userList.size());
     }
 }

+ 69 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2LogicDeleteTest.java

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011-2019, hubin (jobob@qq.com).
+ * <p>
+ * 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.baomidou.mybatisplus.test.h2;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import com.baomidou.mybatisplus.test.h2.entity.H2User;
+import com.baomidou.mybatisplus.test.h2.entity.H2UserLogicDelete;
+import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
+import com.baomidou.mybatisplus.test.h2.mapper.H2UserLogicDeleteMapper;
+
+/**
+ * Mybatis Plus H2 Junit Test
+ *
+ * @author hubin
+ * @since 2018-06-05
+ */
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(locations = {"classpath:h2/spring-logic-delete-h2.xml"})
+class H2LogicDeleteTest extends BaseTest {
+
+    @Resource
+    protected H2UserLogicDeleteMapper logicDeleteMapper;
+
+    @Test
+    @Order(1)
+    void crudTest() {
+        String name = "LogicDelete4Date";
+        H2UserLogicDelete user = new H2UserLogicDelete();
+        user.setAge(AgeEnum.ONE);
+        user.setName(name);
+        logicDeleteMapper.insert(user);
+        Assertions.assertNotNull(user.getTestId(), "id should not be null");
+        Assertions.assertNull(user.getLastUpdatedDt());
+
+        logicDeleteMapper.deleteById(user.getTestId());
+
+        List<H2User> userList = queryByName(name);
+        Assertions.assertTrue(userList!=null && !userList.isEmpty());
+        Assertions.assertNotNull(userList.get(0).getLastUpdatedDt(),"lastUpdateDt should not be null after logic delete");
+
+    }
+
+}

+ 9 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/config/DBConfig.java

@@ -15,18 +15,21 @@
  */
 package com.baomidou.mybatisplus.test.h2.config;
 
+import java.io.IOException;
+
 import javax.sql.DataSource;
+
 import org.h2.Driver;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.jdbc.datasource.SimpleDriverDataSource;
 import org.springframework.jdbc.datasource.init.DataSourceInitializer;
 import org.springframework.jdbc.datasource.init.DatabasePopulator;
 import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
-import java.io.IOException;
 
 /**
  * H2 Memory Database config
@@ -71,4 +74,9 @@ public class DBConfig {
         return resourceDatabasePopulator;
     }
 
+    @Bean
+    public JdbcTemplate jdbcTemplate(DataSource ds){
+        return new JdbcTemplate(ds);
+    }
+
 }

+ 89 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/config/MybatisPlusConfigLogicDelete.java

@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.baomidou.mybatisplus.test.h2.config;
+
+import javax.sql.DataSource;
+
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.EnumOrdinalTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ResourceLoader;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
+import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+
+/**
+ * Mybatis Plus Config
+ *
+ * @author Caratacus
+ * @since 2017/4/1
+ */
+@Configuration
+@MapperScan("com.baomidou.mybatisplus.test.h2.mapper")
+public class MybatisPlusConfigLogicDelete {
+
+    @Bean("mybatisSqlSession")
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ResourceLoader resourceLoader, GlobalConfig globalConfig) throws Exception {
+        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
+        sqlSessionFactory.setDataSource(dataSource);
+//        sqlSessionFactory.setConfigLocation(resourceLoader.getResource("classpath:mybatis-config-object-factory.xml"));
+        sqlSessionFactory.setTypeAliasesPackage("com.baomidou.mybatisplus.test.h2.entity.persistent");
+        MybatisConfiguration configuration = new MybatisConfiguration();
+//        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
+//        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+        configuration.setJdbcTypeForNull(JdbcType.NULL);
+        /*
+         * 下划线转驼峰开启
+         */
+        configuration.setMapUnderscoreToCamelCase(true);
+        configuration.setDefaultExecutorType(ExecutorType.REUSE);
+        configuration.setDefaultEnumTypeHandler(EnumOrdinalTypeHandler.class);  //默认枚举处理
+        sqlSessionFactory.setConfiguration(configuration);
+        PaginationInterceptor pagination = new PaginationInterceptor();
+        OptimisticLockerInterceptor optLock = new OptimisticLockerInterceptor();
+        sqlSessionFactory.setPlugins(new Interceptor[]{
+            pagination,
+            optLock,
+            new PerformanceInterceptor()
+        });
+        sqlSessionFactory.setGlobalConfig(globalConfig);
+        sqlSessionFactory.setTypeEnumsPackage("com.baomidou.mybatisplus.test.h2.enums");
+        return sqlSessionFactory.getObject();
+    }
+
+    @Bean
+    public GlobalConfig globalConfiguration() {
+        GlobalConfig conf = new GlobalConfig();
+        conf.setSqlInjector(new LogicSqlInjector())
+            .setEnableSqlRunner(true)
+            .setDbConfig(new GlobalConfig.DbConfig()
+                .setLogicDeleteValue("NOW()")
+                .setLogicNotDeleteValue("NULL")
+                .setIdType(IdType.ID_WORKER));
+        return conf;
+    }
+}

+ 139 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2UserLogicDelete.java

@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.baomidou.mybatisplus.test.h2.entity;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.Version;
+import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 测试用户类
+ *
+ * @author hubin sjy
+ */
+/* 表名 value 注解【 驼峰命名可无 】, resultMap 注解测试【 映射 xml 的 resultMap 内容 】 */
+@Data
+@Accessors(chain = true)
+@TableName("h2user")
+public class H2UserLogicDelete {
+
+    /**
+	 * serialVersionUID
+	 */
+	private static final long serialVersionUID = 2043176352335589747L;
+
+    @TableId
+    private Long testId;
+
+	/* 测试忽略验证 */
+    private String name;
+
+    private AgeEnum age;
+
+    /*BigDecimal 测试*/
+    private BigDecimal price;
+
+    /* 测试下划线字段命名类型, 字段填充 */
+    @TableField(strategy = FieldStrategy.IGNORED)
+    private Integer testType;
+
+    /**
+     * 转义关键字测试
+     */
+    @TableField("`desc`")
+    private String desc;
+
+    /**
+     * 该注解 select 默认不注入 select 查询
+     */
+    @TableField(select = false)
+    private Date testDate;
+
+    @Version
+    private Integer version;
+
+    private Integer deleted;
+
+    @TableLogic
+    private Date lastUpdatedDt;
+
+
+    public H2UserLogicDelete() {
+
+    }
+
+    public H2UserLogicDelete(String name) {
+        this.name = name;
+    }
+
+    public H2UserLogicDelete(Integer testType) {
+        this.testType = testType;
+    }
+
+    public H2UserLogicDelete(String name, AgeEnum age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    public H2UserLogicDelete(Long id, String name) {
+        this.setTestId(id);
+        this.name = name;
+    }
+
+    public H2UserLogicDelete(Long id, AgeEnum age) {
+        this.setTestId(id);
+        this.age = age;
+    }
+
+    public H2UserLogicDelete(Long id, String name, AgeEnum age, Integer testType) {
+        this.setTestId(id);
+        this.name = name;
+        this.age = age;
+        this.testType = testType;
+    }
+
+    public H2UserLogicDelete(String name, AgeEnum age, Integer testType) {
+        this.name = name;
+        this.age = age;
+        this.testType = testType;
+    }
+
+    public H2UserLogicDelete(String name, Integer deleted) {
+        this.name = name;
+        this.deleted = deleted;
+    }
+
+    @Override
+    public String toString() {
+        return "h2user:{name=" + name + "," +
+            "age=" + age + "," +
+            "price=" + price + "," +
+            "testType=" + testType + "," +
+            "desc=" + desc + "," +
+            "testDate=" + testDate + "," +
+            "version=" + version;
+    }
+}

+ 13 - 1
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/enums/AgeEnum.java

@@ -30,13 +30,25 @@ public enum AgeEnum implements IEnum<Integer> {
 
     private final int value;
     @SuppressWarnings("unused")
-	private final String desc;
+    private final String desc;
 
     AgeEnum(final int value, final String desc) {
         this.value = value;
         this.desc = desc;
     }
 
+    public static AgeEnum parseValue(Integer v) {
+        if (v == null) {
+            return null;
+        }
+        for (AgeEnum e : AgeEnum.values()) {
+            if (e.getValue().equals(v)) {
+                return e;
+            }
+        }
+        return null;
+    }
+
     @Override
     public Integer getValue() {
         return value;

+ 28 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/mapper/H2UserLogicDeleteMapper.java

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * 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
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.baomidou.mybatisplus.test.h2.mapper;
+
+import com.baomidou.mybatisplus.test.h2.entity.H2UserLogicDelete;
+
+/**
+ * 这里继承自定义父类 SuperMapper
+ *
+ * @author Caratacus
+ * @since 2017/4/1
+ */
+public interface H2UserLogicDeleteMapper extends SuperMapper<H2UserLogicDelete> {
+
+}

+ 13 - 0
mybatis-plus/src/test/resources/h2/spring-logic-delete-h2.xml

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <context:component-scan base-package="com.baomidou.mybatisplus.test.h2.service"/>
+
+    <bean name="/DBConfig" class="com.baomidou.mybatisplus.test.h2.config.DBConfig"/>
+    <bean name="/MybatisPlusConfig" class="com.baomidou.mybatisplus.test.h2.config.MybatisPlusConfigLogicDelete"/>
+
+</beans>