通用mapper对sqlserver自增主键如何使用insertSelective插入?

nbcty 2018-06-15 09:06:03
例如insert into table_A(id, name) values(null, '张三'),id为自增列。
在mysql中,是可以插入的。
在sqlserver中,报错“当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'table_A' 中的标识列插入显式值”,解决方法:要么把id列去掉,要么前后加上set identity_insert table_A on和set identity_insert table_A off。

使用insertSelective()插入时,会将没有设置值的字段忽略,但是主键id永远不忽略。
所以使用自增列时,插入语句就像上面一样,还是会有id列,但是对应值为null。

目前,程序中,就出现了上面的问题。同样的程序,使用mysql数据源不报错。使用sqlserver数据库,报错,“当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'table_A' 中的标识列插入显式值”。

如何解决这个问题?
...全文
1414 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
SHI0ELD 2021-05-07
  • 打赏
  • 举报
回复
自己扩展一个独立的带identity_insert开关标识的插入mapper, ``` import org.apache.ibatis.annotations.InsertProvider; import java.util.List; /** * 通用Mapper接口,带identity_insert开关标识的插入方法 */ public interface InsertWithIdentitySwitchMapper<T> { @InsertProvider(type = InsertWithIdentitySwitchProvider.class, method = "dynamicSQL") int insertWithIdentitySwitch(T record); @InsertProvider(type = InsertWithIdentitySwitchProvider.class, method = "dynamicSQL") int insertSelectiveWithIdentitySwitch(T record); @InsertProvider(type = InsertWithIdentitySwitchProvider.class, method = "dynamicSQL") int insertListWithIdentitySwitch(List<T> recordList); } ``` ``` import org.apache.ibatis.mapping.MappedStatement; import tk.mybatis.mapper.entity.EntityColumn; import tk.mybatis.mapper.mapperhelper.EntityHelper; import tk.mybatis.mapper.mapperhelper.MapperHelper; import tk.mybatis.mapper.mapperhelper.MapperTemplate; import tk.mybatis.mapper.mapperhelper.SqlHelper; import java.util.Iterator; import java.util.Set; /** * 带identity_insert开关标识的插入方法实现类 */ public class InsertWithIdentitySwitchProvider extends MapperTemplate { public InsertWithIdentitySwitchProvider(Class<?> mapperClass, MapperHelper mapperHelper) { super(mapperClass, mapperHelper); } public String insertWithIdentitySwitch(MappedStatement ms) { Class<?> entityClass = this.getEntityClass(ms); StringBuilder sql = new StringBuilder(); String tableName = this.tableName(entityClass); sql.append("set identity_insert " + tableName + " on;"); sql.append(SqlHelper.insertIntoTable(entityClass, tableName)); sql.append(SqlHelper.insertColumns(entityClass, true, false, false)); sql.append(SqlHelper.insertValuesColumns(entityClass, true, false, false)); sql.append("set identity_insert " + tableName + " off;"); EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } public String insertSelectiveWithIdentitySwitch(MappedStatement ms) { Class<?> entityClass = this.getEntityClass(ms); StringBuilder sql = new StringBuilder(); String tableName = this.tableName(entityClass); sql.append("set identity_insert " + tableName + " on;"); sql.append(SqlHelper.insertIntoTable(entityClass, tableName)); sql.append(SqlHelper.insertColumns(entityClass, true, true, this.isNotEmpty())); sql.append(SqlHelper.insertValuesColumns(entityClass, true, true, this.isNotEmpty())); sql.append("set identity_insert " + tableName + " off;"); EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } public String insertListWithIdentitySwitch(MappedStatement ms) { Class<?> entityClass = this.getEntityClass(ms); StringBuilder sql = new StringBuilder(); String tableName = this.tableName(entityClass); sql.append("<bind name=\"listNotEmptyCheck\" value=\"@tk.mybatis.mapper.util.OGNL@notEmptyCollectionCheck(list, '" + ms.getId() + " 方法参数为空')\"/>"); sql.append("set identity_insert " + tableName + " on;"); sql.append(SqlHelper.insertIntoTable(entityClass, tableName, "list[0]")); sql.append(SqlHelper.insertColumns(entityClass, true, false, false)); sql.append(" VALUES "); sql.append("<foreach collection=\"list\" item=\"record\" separator=\",\" >"); sql.append("<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">"); Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass); Iterator var5 = columnList.iterator(); while(var5.hasNext()) { EntityColumn column = (EntityColumn)var5.next(); if (!column.isId() && column.isInsertable()) { sql.append(column.getColumnHolder("record") + ","); } } sql.append("</trim>"); sql.append("</foreach>"); sql.append("set identity_insert " + tableName + " off;"); EntityHelper.setKeyProperties(EntityHelper.getPKColumns(entityClass), ms); return sql.toString(); } } ```
小蚂蚁啊 2018-09-11
  • 打赏
  • 举报
回复
通过分析源码,entityhelp与MapperBuilderAssistant ,初步判断是几个原因,
第一个原因是keyProperty defualt='id'(我就是此问题,自增id列名称不为id所以insert未返回自增列值),
第二个原因可能在entityhelp源码中的 逻辑判断 if(generatedValue.generator().equals("UUID")) ... else if(generatedValue.generator().equals("JDBC"))..else{ //这个位置 还有一层逻辑判断
if (generatedValue.strategy() == GenerationType.IDENTITY) {
//当前条件才会执行自增
}
}
----- 所以 可以试试注解-----
@GeneratedValue(generator = "SqlServer",strategy=GenerationType.IDENTITY)

isea533 2018-06-15
  • 打赏
  • 举报
回复
建议用最新版本:4.0.3-beta1,虽然是 beta1,也是稳定的,如果从 3.x 升级到 4.x,一定要看看文档:https://github.com/abel533/Mapper/wiki,专用方法包名:tk.mybatis.mapper.common.sqlserver,里面有两个 insert 方法。BaseId 没实际例子,我的意思是,如果你项目需要同时支持不同数据库,可以创建一个独立的项目如 baseid-mysql,baseid-oracle 这样的,项目中有 BaseId 类,这个类的全限定名是相同的。类是针对不同数据库配置。。如果想要支持mysql,项目下面就用 baseid-mysql.jar,oracle同理。
nbcty 2018-06-15
  • 打赏
  • 举报
回复
引用 12 楼 isea533 的回复:
有两种解决办法。 1.有专门给sqlserver提供的insert方法,在 sqlserver 包中。 2.配置@Column(insertable=false) 如果想兼容不同数据库,建议创建不同版本的BaseId(单独jar),针对不同数据库配置选择jar。
万分感谢!!! 当然,也感谢上面热心回复的网友。
isea533 2018-06-15
  • 打赏
  • 举报
回复
有两种解决办法。 1.有专门给sqlserver提供的insert方法,在 sqlserver 包中。 2.配置@Column(insertable=false) 如果想兼容不同数据库,建议创建不同版本的BaseId(单独jar),针对不同数据库配置选择jar。
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
引用 10 楼 stacksoverflow 的回复:
有个genID注解,希望能帮到你 https://www.oschina.net/news/95432/mapper-4-0-2-released
看错了,当我没说,先忙别的了。
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
有个genID注解,希望能帮到你 https://www.oschina.net/news/95432/mapper-4-0-2-released
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
引用 8 楼 nbcty 的回复:
哥呀,我用的是通用mapper(tk.mybatis),不用写mapper文件! 这种原始写法,肯定能解决问题,但是整个工程要改好几十处,太费事了。
大概猜到你没用原始的了,我不喜欢用这些高级的,有时候明明白白改10几处也挺好。 请楼下再帮忙看看吧。
nbcty 2018-06-15
  • 打赏
  • 举报
回复
哥呀,我用的是通用mapper(tk.mybatis),不用写mapper文件! 这种原始写法,肯定能解决问题,但是整个工程要改好几十处,太费事了。
nbcty 2018-06-15
  • 打赏
  • 举报
回复
引用 3 楼 stacksoverflow 的回复:
insert语句不写ID,配置设置为 useGeneratedKeys="true", 用数据库自己的自增就可以了。
配置已经为 useGeneratedKeys="true",对象也没setId(),但是insert()和insertSelective()方法生成的sql中还是有id列,值为null。
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
参考 http://www.raistudies.com/mybatis/inserting-auto-generated-id-using-mybatis-return-id-to-java/
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
insert语句不写ID,配置设置为 useGeneratedKeys="true", 用数据库自己的自增就可以了。
nbcty 2018-06-15
  • 打赏
  • 举报
回复
引用 1 楼 stacksoverflow 的回复:
参考 https://github.com/baomidou/mybatis-plus/issues/183
我用的是通用mapper,不是Mybatis-Plus
stacksoverflow 2018-06-15
  • 打赏
  • 举报
回复
参考 https://github.com/baomidou/mybatis-plus/issues/183

81,092

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧