Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于updateByPrimaryKeySelective(T)主键异常问题 #875

Open
SMSshuai opened this issue Feb 9, 2023 · 10 comments
Open

关于updateByPrimaryKeySelective(T)主键异常问题 #875

SMSshuai opened this issue Feb 9, 2023 · 10 comments

Comments

@SMSshuai
Copy link

SMSshuai commented Feb 9, 2023

通过updateByPrimaryKeySelective(T)方法更新数据的时候主键ID会变化

数据库主键ID自增
如id =10 ,11, 12,13 ,因业务需求删除了其中一个id =11。
在执行updateByPrimaryKeySelective方法是传入的数据id是12 ,但是执行成功后,实体内的id变成了11(这个id数据不存在,实体内的其他数据都正常)。
后续测试后发现,执行该方法后如果该条数据的id大于空缺数据的id就会返回空数据id。
比如:删除了id11
更新id<11的数据都正常。
更新id>11的数据都会返回id=11.
如果删除多条数据,会返回正序第一个被删掉的id。

实体增加了如下注解
@id
@keysql(useGeneratedKeys = true)
@column(insertable = false,updatable = false)
@ApiModelProperty(value="id")
private Long id;

数据对比
代码执行截图

打印出来的执行代码如下
UPDATE sys_configye SET business_name = 'AppHomeStyle',business_code = 'rule',begin_time = '2022-01-01 15:08:43.0',end_time = '2030-01-12 15:08:44.0',type = 0,content_A = 4,content_B = 1,content_C = '通知公告',content_D = 'notification'
WHERE id = 12;

@abel533
Copy link
Owner

abel533 commented Feb 9, 2023

使用 useGeneratedKeys 时,可能是JDBC的问题,你试试纯JDBC有没有问题。

@SMSshuai
Copy link
Author

SMSshuai commented Feb 9, 2023

使用 useGeneratedKeys 时,可能是JDBC的问题,你试试纯JDBC有没有问题。
直接用倒是可以~数据都正常。
这个问题有啥办法替代或者解决方案吗?我这边是在做数据库迁移适配的时候遇到的问题,因为使用的范围和数量都很广,逐个重写很困难。
int abcdefg(SysConfigye sysConfigye);

<update id="abcdefg" parameterType="com.sdyx.system.domain.SysConfigye" >
    UPDATE sys_configye
    SET business_name = #{businessName},
        business_code = #{businessCode},
        begin_time = #{beginTime},
        end_time = #{endTime},
        type = #{type},
        content_A = #{contentA},
        content_B = #{contentB},
        content_C = #{contentC},
        content_D = #{contentD}
        WHERE
        id = #{id}
</update>

@SMSshuai
Copy link
Author

SMSshuai commented Feb 9, 2023

使用 useGeneratedKeys 时,可能是JDBC的问题,你试试纯JDBC有没有问题。

刚才更新了达梦数据库驱动包和最新的tk包,数据恢复正常了。可能是兼容问题。感谢回复

tk.mybatis
mapper-spring-boot-starter
4.2.2


com.dameng
DmJdbcDriver18
8.1.2.141

@blackkeai
Copy link

使用 useGeneratedKeys 时,可能是JDBC的问题,你试试纯JDBC有没有问题。

刚才更新了达梦数据库驱动包和最新的tk包,数据恢复正常了。可能是兼容问题。感谢回复 tk.mybatis mapper-spring-boot-starter 4.2.2 com.dameng DmJdbcDriver18 8.1.2.141

你好,你达梦数据库用的哪个 方言?

@LSL1618
Copy link

LSL1618 commented Jul 5, 2023

我也遇到了类似情况,在使用SQLServer数据库时updateByExampleSelective执行报错,说无法更新主键标识列,查了4.2.1、4.2.2这2个版本的源码,发现在类方法SqlHelper.updateSetColumnsIgnoreVersion()中,4.2.2及以上版本多了这一段代码片

else if (column.isId() && column.isUpdatable()) {
    sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(",");
}

导致主键标识列也加入了被更新字段,SQLServer不允许自然就报错了。
别的数据库我不清楚,但这段代码片在使用SQLServer数据库时是不合理的,应该区分开。

1 similar comment
@LSL1618
Copy link

LSL1618 commented Jul 5, 2023

我也遇到了类似情况,在使用SQLServer数据库时updateByExampleSelective执行报错,说无法更新主键标识列,查了4.2.1、4.2.2这2个版本的源码,发现在类方法SqlHelper.updateSetColumnsIgnoreVersion()中,4.2.2及以上版本多了这一段代码片

else if (column.isId() && column.isUpdatable()) {
    sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(",");
}

导致主键标识列也加入了被更新字段,SQLServer不允许自然就报错了。
别的数据库我不清楚,但这段代码片在使用SQLServer数据库时是不合理的,应该区分开。

@SMSshuai
Copy link
Author

SMSshuai commented Jul 5, 2023

使用 useGeneratedKeys 时,可能是JDBC的问题,你试试纯JDBC有没有问题。

刚才更新了达梦数据库驱动包和最新的tk包,数据恢复正常了。可能是兼容问题。感谢回复 tk.mybatis mapper-spring-boot-starter 4.2.2 com.dameng DmJdbcDriver18 8.1.2.141

你好,你达梦数据库用的哪个 方言?

Mysql

@LSL1618
Copy link

LSL1618 commented Jul 5, 2023

我也遇到了类似情况,在使用SQLServer数据库时updateByExampleSelective执行报错,说无法更新主键标识列,查了4.2.1、4.2.2这2个版本的源码,发现在类方法SqlHelper.updateSetColumnsIgnoreVersion()中,4.2.2及以上版本多了这一段代码片

else if (column.isId() && column.isUpdatable()) {
    sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(",");
}

导致主键标识列也加入了被更新字段,SQLServer不允许自然就报错了。
别的数据库我不清楚,但这段代码片在使用SQLServer数据库时是不合理的,应该区分开。

@gbpyz
Copy link

gbpyz commented Apr 25, 2024

我也遇到了类似情况,在使用SQLServer数据库时updateByExampleSelective执行报错,说无法更新主键标识列,查了4.2.1、4.2.2这2个版本的源码,发现在类方法SqlHelper.updateSetColumnsIgnoreVersion()中,4.2.2及以上版本多了这一段代码片

else if (column.isId() && column.isUpdatable()) {
    sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(",");
}

导致主键标识列也加入了被更新字段,SQLServer不允许自然就报错了。 别的数据库我不清楚,但这段代码片在使用SQLServer数据库时是不合理的,应该区分开。

我也遇到了这个情况,现在回滚到了4.2.1,请问这个问题高版本解决了吗

@LSL1618
Copy link

LSL1618 commented Apr 26, 2024

我也遇到了类似情况,在使用SQLServer数据库时updateByExampleSelective执行报错,说无法更新主键标识列,查了4.2.1、4.2.2这2个版本的源码,发现在类方法SqlHelper.updateSetColumnsIgnoreVersion()中,4.2.2及以上版本多了这一段代码片

else if (column.isId() && column.isUpdatable()) {
    sql.append(column.getColumn()).append(" = ").append(column.getColumn()).append(",");
}

导致主键标识列也加入了被更新字段,SQLServer不允许自然就报错了。 别的数据库我不清楚,但这段代码片在使用SQLServer数据库时是不合理的,应该区分开。

我也遇到了这个情况,现在回滚到了4.2.1,请问这个问题高版本解决了吗

高版本并没有处理这个问题,所以我只好自己解决了,在所有表实体类的自增长主键标识列的@column注解中设置 insertable=false、updatable=false,如果有自定义通用Mapper方法要检查一下是否用到 column.isInsertable()、column.isUpdatable() ,酌情处理是否去掉它两。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants