@Insert和@InsertProvider的使用
首先,在mybatis-generator.xml中配置返回主键
UserMapper中的
@SelectKey
:返回主键,具体解释见下面说明@InsertProvider
:type指明SQL工厂类,method是工厂类里对应的方法
@SelectKey注解源码
statement
是要运行的SQL语句,它的返回值通过resultType来指定before表示查询语句statement运行的时机keyProperty
表示查询结果赋值给代码中的哪个对象,keyColumn表示将查询结果赋值给数据库表中哪一列keyProperty
和keyColumn都不是必需的,有没有都可以before=true
,插入之前进行查询,可以将查询结果赋给keyProperty和-keyColumn,赋给keyColumn相当于更改数据库befaore=false
,先插入,再查询,这时只能将结果赋给keyProperty- 赋值给
keyProperty
用来“读”数据库,赋值给keyColumn用来写数据库
selectKey的两大作用:
- 1、生成主键;
- 2、获取刚刚插入数据的主键。
注意:在MYSQL 中 , order是AFTER , 因为当前及记录的主键值在insert语句执行成功之后才能拿到 , 而在ORACLE中 ,oder是BEFORE , 因为ORACLE需要先从序列取到值 , 再将其作为主键插入到数据库
另外,附上UserMapper.xml形式的返回主键方法
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
实体类的映射文件
namespace 指定接口的类全名
-->
<mapper namespace="com.wzl.dao.UserMapper">
<!--
方案一: 这表的主键必须是自增长的 auto_increment
useGeneratedKeys="true" 让自增长的主键开启返回功能
keyColumn="id" user表中主键列
keyProperty="id" user实体主键属性
注意:支持主键自增类型的数据库 MySQL 和 SqlServer , oracle不支持
-->
<insert id="addUser" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into user values(null,#{user.username},#{user.birthday},#{user.sex},#{user.address})
</insert>
<!--
方案二: <selectKey>
keyColumn="id" user表中主键列
keyProperty="id" user实体主键属性
resultType="int" user实体主键属性类型
order="AFTER" 表示此标签内部sql语句在insert执行之前(执行),还是之后执行(执行)
AFTER 之后执行【在自增主键时】
BEFORE 之前执行【使用指定主键时】
在MYSQL 中 , order是AFTER , 因为当前及记录的主键值在insert语句执行成功之后才能拿到 , 而在ORACLE中 ,oder是BEFORE , 因为ORACLE需要先从序列取到值 , 再将其作为主键插入到数据库
-->
<insert id="addUser2">
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user values(null, #{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
使用InsertProvider注解报错解决过程
目前项目在使用mybatis,并且是使用注解的方式。
在使用InsertProvider注解的时候报了一下的错误:
org.apache.ibatis.builder.BuilderException: Could not find value method on SQL annotation. Cause: org.apache.ibatis.builder.BuilderException: Error creating SqlSource for SqlProvider. Method........
注解是如下这个样子的
@InsertProvider(method = "insertlist",type=SqlProvider.class)
public int insertInnerTable(List list,String dbTable);
思路是要写一个通用的插入一个集合的方法,但是在执行的时候就报了上面的错误。在网上查资料未果。
于是只能自己动手,丰衣足食了。
一步步跟断点,跟到mybatis了报错的方法中,发现了如下的代码
try {
this.sqlSourceParser = new SqlSourceBuilder(config);
this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
for (Method m : this.providerType.getMethods()) {
if (providerMethodName.equals(m.getName())) {
if (m.getParameterTypes().length < 2
&& m.getReturnType() == String.class) {
this.providerMethod = m;
this.providerTakesParameterObject = m.getParameterTypes().length == 1;
}
}
}
} catch (Exception e) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Cause: " + e, e);
}
注意标黄的位置,终于发现导致错误的罪魁祸首了,原来是这里限制了参数的个数,不能操作两个参数的啊。
于是将方法以及注解改为如下形式
@InsertProvider(method = "insert",type=SqlProvider.class)
public int insert(SqlContext sqlContext);
在SqlProvider中对应的方法为
public String insert(SqlContext sqlContext){
........
}
至此问题解决!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。