栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

tk.mybatis 根据主键id执行update操作时,组装的sql语句包含了非id列

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

tk.mybatis 根据主键id执行update操作时,组装的sql语句包含了非id列

tk.mybatis使用updateByPrimaryKeySelective 的where条件多了非id字段
  • 错误代码
    • 错误完整Java执行代码
    • 问题分析
    • 问题原因
    • 解决方案

错误代码 错误完整Java执行代码

实体类

@Table(name = "test")
public class Test  {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

   

    
    private Boolean status;

    
    @Column(name = "create_time")
    private Date createTime;

    
    @Column(name = "creator_id")
    private Integer creatorId;

    
    private String creator;

    
    @Column(name = "modify_time")
    private Date modifyTime;

    
    @Column(name = "modifier_id")
    private Integer modifierId;

    
    private String modifier;

    
    private String remark;

   // -----省略get,set方法
}

mapper文件(对应的xml文件就不在此列出了)

import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeyMapper;

public interface TestMapper extends UpdateByPrimaryKeyMapper {

}

Java调用

@Resource
private TestMapper testMapper;

public void update(){
	Test test = new Test();
	test.setId(12);
	test.setRemark("sjiji);
	testMapper.updateByPrimaryKey(test);
}

上面为代码详情。在执行update的时候。发现sql语句会如下

	 update test set remark = 'sjiji' where id = 12 and remark = null and modifier = null and  modifierId = null and modifyTime = null and creator = null and creatorId = null and createTime = null and status = null

很显然上面的sql 是错误的sql ;where条件后面包含了非id字段列;

问题分析

找了很久发现原因;

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package tk.mybatis.mapper.common.base.update;

import org.apache.ibatis.annotations.UpdateProvider;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.provider.base.baseUpdateProvider;

@RegisterMapper
public interface UpdateByPrimaryKeySelectiveMapper {
    @UpdateProvider(
        type = baseUpdateProvider.class,
        method = "dynamicSQL"
    )
    int updateByPrimaryKeySelective(T var1);
}


上面的update会调用 baseUpdateProvider#updateByPrimaryKeySelective方法;实现如下

   public String updateByPrimaryKeySelective(MappedStatement ms) {
        Class entityClass = this.getEntityClass(ms);
        StringBuilder sql = new StringBuilder();
        sql.append(SqlHelper.updateTable(entityClass, this.tableName(entityClass)));
        sql.append(SqlHelper.updateSetColumns(entityClass, (String)null, true, this.isNotEmpty()));
        //拼接where条件列
        sql.append(SqlHelper.wherePKColumns(entityClass, true));
        return sql.toString();
    }

拼接where条件后面的sql处理逻辑

public static String wherePKColumns(Class entityClass, String entityName, boolean useVersion) {
        StringBuilder sql = new StringBuilder();
        boolean hasLogicDelete = hasLogicDeleteColumn(entityClass);

        sql.append("");
        //获取全部列
        Set columnSet = EntityHelper.getPKColumns(entityClass);
        //当某个列有主键策略时,不需要考虑他的属性是否为空,因为如果为空,一定会根据主键策略给他生成一个值
        for (EntityColumn column : columnSet) {
            sql.append(" AND ").append(column.getColumnEqualsHolder(entityName));
        }
        if (useVersion) {
            sql.append(whereVersion(entityClass));
        }

        if (hasLogicDelete) {
            sql.append(whereLogicDelete(entityClass, false));
        }

        sql.append("");
        return sql.toString();
    }

设置当前实体类的id字段的方法 tk.mybatis.mapper.mapperhelper.resolve.DefaultEntityResolve#resolveEntity

public EntityTable resolveEntity(Class entityClass, Config config) {
        Style style = config.getStyle();
        //style,该注解优先于全局配置
        if (entityClass.isAnnotationPresent(NameStyle.class)) {
            NameStyle nameStyle = entityClass.getAnnotation(NameStyle.class);
            style = nameStyle.value();
        }

        //创建并缓存EntityTable
        EntityTable entityTable = null;
        if (entityClass.isAnnotationPresent(Table.class)) {
            Table table = entityClass.getAnnotation(Table.class);
            if (!"".equals(table.name())) {
                entityTable = new EntityTable(entityClass);
                entityTable.setTable(table);
            }
        }
        if (entityTable == null) {
            entityTable = new EntityTable(entityClass);
            //可以通过stye控制
            String tableName = StringUtil.convertByStyle(entityClass.getSimpleName(), style);
            //自动处理关键字
            if (StringUtil.isNotEmpty(config.getWrapKeyword()) && SqlReservedWords.containsWord(tableName)) {
                tableName = MessageFormat.format(config.getWrapKeyword(), tableName);
            }
            entityTable.setName(tableName);
        }
        entityTable.setEntityClassColumns(new linkedHashSet());
        entityTable.setEntityClassPKColumns(new linkedHashSet());
        //处理所有列
        List fields = null;
        if (config.isEnableMethodAnnotation()) {
            fields = FieldHelper.getAll(entityClass);
        } else {
            fields = FieldHelper.getFields(entityClass);
        }
        for (EntityField field : fields) {
            //如果启用了简单类型,就做简单类型校验,如果不是简单类型,直接跳过
            //3.5.0 如果启用了枚举作为简单类型,就不会自动忽略枚举类型
            //4.0 如果标记了 Column 或 ColumnType 注解,也不忽略
            if (config.isUseSimpleType()
                    && !field.isAnnotationPresent(Column.class)
                    && !field.isAnnotationPresent(ColumnType.class)
                    && !(SimpleTypeUtil.isSimpleType(field.getJavaType())
                    ||
                    (config.isEnumAsSimpleType() && Enum.class.isAssignableFrom(field.getJavaType())))) {
                continue;
            }
            // 方法逻辑会执行设置主键id及其他字段信息
            processField(entityTable, field, config, style);
        }
        //当pk.size=0的时候使用所有列作为主键
        if (entityTable.getEntityClassPKColumns().size() == 0) {
            entityTable.setEntityClassPKColumns(entityTable.getEntityClassColumns());
        }
        entityTable.initPropertyMap();
        return entityTable;
    }

tk.mybatis.mapper.mapperhelper.resolve.DefaultEntityResolve#processField处理的id逻辑

 protected void processField(EntityTable entityTable, EntityField field, Config config, Style style) {
 		// 需要加上 @Id注解
        if (field.isAnnotationPresent(Id.class)) {
            entityColumn.setId(true);
        }
      }
问题原因

再看我们的实体,发现实体类没有 @ID 注解。。。。

解决方案

所以此处解决方案,给实体类加上 @Id注解即可

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/337103.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号