使用mybatis + mybatis-generator + pgsql,设置了pgsql主键自增.
遇到两个问题.
1.新增失败,提示数据库中主键对应那一列不能为空.
问题原因:
这是因为我使用了生成器中的insert方法.仔细看,方法中sql语句会将主键赋值.而我们使用自增主键,一般不会给入参对象的主键值,这一个属性因而为null.主键是非空的,所以报错.
解决方法:
使用生成器中的insertSelective方法,因为有if判断,当入参中某属性为空,拼接成的sql语句里没有新增该列的内容.
2.新增后,获取自增id失败,报错类型转换错误.
问题原因:
我的数据库里,主键类型是bigint,数据实体类里,是Long.完全对的上,最后却报错不良的类型值 long.
我使用的方法是,在insert标签内,使用keyProperty标记数据实体类的主键.useGeneratedKeys标记这是一个自增主键.类似下面
<insert id="insertSelective" keyProperty="数据实体类里的主键id名" useGeneratedKeys="true" parameterType="数据实体类的名">
如果正常,那么会在新增完成后,将实体类中自增的主键属性,放入keyProperty对应的属性.
然后只需要获取调用mapper方法时,作为入参的数据实体类里的这个主键属性就可以得到值.
实体类入参在主键自增长的时候,本来程序员不会赋值主键,主键属性是null.现在新增完成后,它会填充到.keyProperty给定的属性中.所以你可以在keyProperty中写任意一个这个入参里的属性,最后都会赋值,只要数据类型对得上.
最后我就是这样发现问题,把一个字符串类型的属性给keyProperty,发现居然是一个时间格式的字符串.应该是新增时间,我不明白为什么是这个.但是最后我询问gpt,给了我解决办法.
解决方法:
在keyProperty和useGeneratedKeys两个标记不变的情况下,只需要在标签尾部新增pgsql函数:RETURNING 你的主键名称.这样就解决了.这里的标签尾部,指的是mybatis组装出的sql的结尾.例如
<insert id="insertSelective" keyProperty="主键id" useGeneratedKeys="true" parameterType="数据实体类名">
省略....
RETURNING 你的主键名称
</insert>
注意:
最后获取自增主键,不是由mapper的insertSelective方法返回的,而是调用mapper的insertSelective方法之后,insertSelective方法会将自增的主键id填写到insertSelective方法的那个实体类入参的主键对应属性内.
正确获取:
xxxmapper.insertSelective(实体类入参A);
自增主键 = 实体类入参A.get主键属性();
错误获取:
自增主键 = xxxmapper.insertSelective(实体类入参A);
insertSelective方法实际上只会返回数据库变更行,所以按照我们一般插入一条数据,最后你按照错误方式获取,怎么获取都是1.