需求:使用MyBatis往MySQL数据库中插入一条记录后,需要返回该条记录的自增主键值。

方法:在mapper中指定keyProperty属性,示例如下:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="userId" parameterType="cn.stu.entity.UserEntity">
    insert into user(userName,password,comment)  
    values(#{userName},#{password},#{comment})  
</insert>

注意:此处可能会有

如果在<insert>的右边尖括号之后有空格,在启动时可能会报:元素类型 "insert" 必须后跟属性规范 ">" 或 "/>"并且,在作新增操作时会一直增不进去而报SQL语法错误,碰到这类问题就把<insert>标签整体在敲一边就可以了

如上所示,我们在insert中指定了keyProperty="userId",其中userId代表插入的User对象的主键属性

User.java

public class User {  
    private int userId;  
    private String userName;  
    private String password;  
    private String comment;  
      
    //setter and getter  
}  

 UserDao.java

public interface UserDao {  
  
    public int insertAndGetId(User user);  
  
}  

 测试:

Java代码  

User user = new User();  
user.setUserName("chenzhou");  
user.setPassword("xxxx");  
user.setComment("测试插入数据返回主键功能");  
  
System.out.println("插入前主键为:"+user.getUserId());  
userDao.insertAndGetId(user);//插入操作  
System.out.println("插入后主键为:"+user.getUserId());  

 输出:

  1. 插入前主键为:0  
  2. 插入后主键为:15  

 查询数据库:

如上所示,刚刚插入的记录主键id为15

总结:用了这个useGenerateKeys="true"后,不用再在写一句关于select的SQL(降低数据库的压力)而直接能够得到刚刚插进去的那个主键,但是——这个属性只能用在主键能自增长的数据库里面比如MySQL可以用,但是oracle就不能用了!

对于oracle返回自增主键(oracle序列)使用selectKey

相关属性如下:

  • keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性
  • order:相对于insert语句来说它的执行顺序,只要不是自增主键,那么就设置为before
  • resultType:指定返回的结果类型

具体使用时:

  • 主键返回之自增主键 SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值只适用于自增主键
<insert  id="addUser" parameterType="cn.entity.Userinfo">
        <selectKey keyProperty="userId" order="AFTER" resultType="java.lang.Long">
             SELECT LAST_INSERT_ID()
        </selectKey>   
        insert into userinfo (userId,userName,userpass,usertype,address) values(#{userId},#{userName},#{userPass},#{userType},#{address})
</insert>
  • 主键返回值UUID : order:如果主键自增,那么为after;如果主键不自增,那么为before,其中UUID函数是mysql的函数
<insert id="insert" parameterType="cn.entity.Userinfo"> 
            <!-- 此处的主键不让自增,而是显示的赋值 -->
                <selectKey keyProperty="id" resultType="java.lang.String" order="before">
                    select UUID()
                </seledtKey>
                insert into userinfo (userId,userName,userpass,usertype,address) values(#{userId},#{userName},#{userPass},#{userType},#{address})
</insert>
  • 主键返回值序列 : order:只要不是自增主键,那么就设置为before,序列也就是sequence,它是Oracle的主键生成策略
<insert id="insert" parameterType="cn.entity.Userinfo"> 
                <selectKey keyProperty="userId" resultType="java.lang.String" order="before">
                    select seq.nextval from dual
                </seledtKey>
                insert into
                     userinfo (userId,userName,userpass,usertype,address) 
                values
                    (#{userId},#{userName},#{userPass},#{userType},#{address})

</insert>

Oracle批量插入

一般在MySQL或者oracle里面直接批量SQL是:

insert into login 
select null,'nihoa' from dual union all
select null,'nihoa' from dual

但是这样的写法要注意——千万不能有values,否则报错

另外,在mybatis里面的oracle 批量插入的时候还必须用到假表select a.* from () a,用到主键自己增长的必须把序列放到同一级别

insert into login(id,name)
select sequence.nextval,a.* from(
<foreach collection="list" item="item" index="index" close=")" open="(" separator="union all">
select
#{item.name}
from dual
</foreach>
) a

oracle自己增长的话,必须把序列放到和假表的同一级别,否则回报一个:序列号不允许使用

附录:JDBC返回生成主键

Connection con=null;
PreparedStatement ps=null;
con = JDBCManager.getConnection();
String sql="insert into users(name,password) values(?,?)";
try {
ps = con.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//获取返回的主键;
ps.setString(1, "qq");
ps.setString(2, "123");
ps.executeUpdate();
ResultSet rs=ps.getGeneratedKeys();//返回一个结果集,保存着产生的key的结果集,
while(rs.next()){
 System.out.println(rs.getObject(1));//结果集只有一个值;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JDBCManager.DBclose(con, ps, null);
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐