侧边栏壁纸
  • 累计撰写 86 篇文章
  • 累计创建 41 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

重写 MyBatis Plus 通用方法 使用 Oracle 数据库,字段类型为 DATE,实体属性类型为 String,通用方法无法使用 to_date 函数

已删除用户
2020-08-19 / 0 评论 / 0 点赞 / 92 阅读 / 0 字

版本:mybatis-plus-boot-starter 3.3.2、3.4.0

刚开始走了弯路,想着通过 Oracle 解决,先是修改了 NLS_DATE_FORMAT,结果发现不适用 JDBC。当然也可以写触发器,每次执行 SQL 前修改这个参数,但是肯定会影响性能。

解决方案是重写通用 insert 方法,用到了 @TableField 注解的 update 属性。

1. 重写通用 insert 方法

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.methods.Insert;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.type.JdbcType;

import java.util.List;

/**
 * 注意 MyBatis Plus 升级版本后需要同步其源码
 * <p>
 * 重写通用 insert 方法,主要为了解决数据库中字段类型为 DATE,实体类中属性类型为 String 时需要使用 TO_DATE 函数的问题
 */
public class MyInsert extends Insert {

  // /**
  //  * 3.3.2
  //  *
  //  * @param mapperClass
  //  * @param modelClass
  //  * @param tableInfo
  //  * @return
  //  */
  // @Override
  // public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
  //   KeyGenerator keyGenerator = new NoKeyGenerator();
  //   SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
  //   String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf(), "(", ")", (String) null, ",");
  //   String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf((String) null), "(", ")", (String) null, ",");
  //   String keyProperty = null;
  //   String keyColumn = null;
  //
  //   // region 自定义内容,其他皆为源码 com.baomidou.mybatisplus.core.injector.methods.Insert.injectMappedStatement
  //   List<TableFieldInfo> tableFieldInfoList = tableInfo.getFieldList();
  //   for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
  //     JdbcType jdbcType = tableFieldInfo.getJdbcType();
  //     String update = tableFieldInfo.getUpdate();
  //     if (jdbcType != null && jdbcType.equals(JdbcType.DATE) && tableFieldInfo.getPropertyType().isAssignableFrom(String.class) && update.toLowerCase().contains("to_date(")) {
  //       valuesScript = valuesScript.replace("#{" + tableFieldInfo.getProperty() + ",jdbcType=" + jdbcType + "}", "#" + update.replaceAll("#\\{et\\..*}", tableFieldInfo.getProperty() + ",jdbcType=" + jdbcType));
  //     }
  //   }
  //   // endregion
  //
  //   if (StringUtil.isNotBlank(tableInfo.getKeyProperty())) {
  //     if (tableInfo.getIdType() == IdType.AUTO) {
  //       keyGenerator = new Jdbc3KeyGenerator();
  //       keyProperty = tableInfo.getKeyProperty();
  //       keyColumn = tableInfo.getKeyColumn();
  //     } else if (null != tableInfo.getKeySequence()) {
  //       keyGenerator = TableInfoHelper.genKeyGenerator(this.getMethod(sqlMethod), tableInfo, this.builderAssistant);
  //       keyProperty = tableInfo.getKeyProperty();
  //       keyColumn = tableInfo.getKeyColumn();
  //     }
  //   }
  //
  //   String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
  //   SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
  //   return this.addInsertMappedStatement(mapperClass, modelClass, this.getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
  // }

  /**
   * 3.4.0
   *
   * @param mapperClass
   * @param modelClass
   * @param tableInfo
   * @return
   */
  @Override
  public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
    KeyGenerator keyGenerator = new NoKeyGenerator();
    SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
    String columnScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlColumnMaybeIf((String) null), "(", ")", (String) null, ",");
    String valuesScript = SqlScriptUtils.convertTrim(tableInfo.getAllInsertSqlPropertyMaybeIf((String) null), "(", ")", (String) null, ",");
    String keyProperty = null;
    String keyColumn = null;

    // region 自定义内容,其他皆为源码 com.baomidou.mybatisplus.core.injector.methods.Insert.injectMappedStatement
    List<TableFieldInfo> tableFieldInfoList = tableInfo.getFieldList();
    for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
      JdbcType jdbcType = tableFieldInfo.getJdbcType();
      String update = tableFieldInfo.getUpdate();
      if (jdbcType != null && jdbcType.equals(JdbcType.DATE) && tableFieldInfo.getPropertyType().isAssignableFrom(String.class) && update.toLowerCase().contains("to_date(")) {
        valuesScript = valuesScript.replace("#{" + tableFieldInfo.getProperty() + ",jdbcType=" + jdbcType + "}", update.replaceAll("#\\{et\\..*}", "#{" + tableFieldInfo.getProperty() + "}"));
      }
    }
    // endregion

    if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
      if (tableInfo.getIdType() == IdType.AUTO) {
        keyGenerator = new Jdbc3KeyGenerator();
        keyProperty = tableInfo.getKeyProperty();
        keyColumn = tableInfo.getKeyColumn();
      } else if (null != tableInfo.getKeySequence()) {
        keyGenerator = TableInfoHelper.genKeyGenerator(this.getMethod(sqlMethod), tableInfo, this.builderAssistant);
        keyProperty = tableInfo.getKeyProperty();
        keyColumn = tableInfo.getKeyColumn();
      }
    }

    String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
    SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);
    return this.addInsertMappedStatement(mapperClass, modelClass, this.getMethod(sqlMethod), sqlSource, (KeyGenerator) keyGenerator, keyProperty, keyColumn);
  }
}

2. 自定义 SQL 注入器

/**
 * 自定义 SQL 注入器,用于新增通用方法
 */
@Component
public class MySqlInjector extends DefaultSqlInjector {

  @Override
  public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
    List<AbstractMethod> methodList = super.getMethodList(mapperClass);
    // 替换 insert 通用方法
    for (int i = 0; i < methodList.size(); i++) {
      if (methodList.get(i) instanceof Insert) {
        methodList.set(i, new MyInsert());
        break;
      }
    }
    return methodList;
  }
}

3. 实体类做修改

import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import org.apache.ibatis.type.JdbcType;

import java.io.Serializable;

@KeySequence("SEQ_FLT_SEASON")
@Data
public class FlightSeason implements Serializable {

  private static final long serialVersionUID = 1L;

  // ……
  
  /**
   * 开始时间
   */
  @TableField(jdbcType = JdbcType.DATE, update = "to_date(#{et.startTime},'yyyy-mm-dd hh24:mi:ss')")
  private String startTime;
  /**
   * 结束时间
   */
  @TableField(jdbcType = JdbcType.DATE, update = "to_date(#{et.endTime},'yyyy-mm-dd hh24:mi:ss')")
  private String endTime;
  
  // ……
}

参考

0

评论区