`
JetMah
  • 浏览: 72597 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

SimpleJdbcInsert使用executeAndReturnKeyHolder方法返回主键时需要注意的一个地方

阅读更多

原文出处: http://www.javatang.com/archives/2010/08/09/3212438.html
作者: Jet Mah from Java堂
声明: 可以非商业性任意转载, 转载时请务必以超链接形式标明文章原始出处、作者信息及此声明!

 

Spring的SimpleJdbcInsert发挥了Simple风格,与SimpleJdbcTemplate同属于Simple体系。该类为向数据库中插入数据提供了一个非常快捷的方式,另外它还提供了一套用于返回插入数据的主键的方法:executeAndReturnKeyHolder、executeAndReturnKey。

 

查看API的时候可以看到executeAndReturnKey这个方法的返回类型是Number类型,当时我就再想如果主键的类型是String类型呢,比如UUID。后来看到还有一个executeAndReturnKeyHolder方法,返回的是一个KeyHolder对象,可以通过keyHolder#getKeys()获取主键的值,另外还有一个getKeyList()方法用于复合主键的情况,这里先撇开不说。

 

看完API之后那就可以动手了,代码如下:

  1. // jdbcInsert是SimpleJdbcInsert对象
  2. Map<String, Object> data = Maps.newHashMap();
  3. data.put("id", "t0001");
  4. data.put("name", "Tom");
  5. data.put("age", 24);
  6. KeyHolder keyHolder = jdbcInsert.withTableName("t_tablename")
  7.         .usingColumns("id", "name", "age")
  8.         .usingGeneratedKeyColumns("id")
  9.         .executeAndReturnKeyHolder(data);
  10. // 下面主要是对keyHoder进行分析
  11. if(keyHolder == null) {
  12.     return null;
  13. }
  14. Map<String, Object> keys = keyHolder.getKeys();
  15. if(keys == null || keys.size() == 0 || keys.values().size() == 0) {
  16.     return null;
  17. }
  18. Object key = keys.values().toArray()[0];
  19. if(key == null || !(key instanceof Serializable)) {
  20.     return null;
  21. }
  22. if(key instanceof Number) {
  23.     Long k = (Long)key;
  24.     return (idType == int.class || idType == Integer.class) ?
  25.             k.intValue() : k;
  26. } else if(key instanceof String) {
  27.     return (String)key;
  28. } else {
  29.     return (Serializable)key;
  30. } // end of if(key instanceof Number)

 

如果主键id的类型是int或long上面的代码没有任何问题,但是如果是自定义的UUID等String类型则问题出现了,提示下面的错误:

org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [HY000]; error code [1364]; Field ‘id’ doesn’t have a default value; nested exception is java.sql.SQLException: Field ‘id’ doesn’t have a default value

有些奇怪了吧?明明id的值已经传入了,但是错误的提示应该是没有传入id的值。进入到Spring的源代码中,发现代码里面有一些debug信息,于是在log4j中将debug打开:

  1. log4j.logger.org.springframework.jdbc.core=debug

 

从打印出来的信息中看,Spring自动生成的Insert语句中竟然没有id字段!!!继续最终源代码,先在org.springframework.jdbc.core.simple.AbstractJdbcInsert类中找到protected void compileInternal()方法,在代码前加上一个debug信息:

  1. protected void compileInternal() {
  2.     logger.debug("getGeneratedKeyNames: " + getColumnNames());
  3.     tableMetaDataContext.processMetaData(getJdbcTemplate().getDataSource(), getColumnNames(), getGeneratedKeyNames());
  4.     ...
  5. }

 

这个时候打印的列表中有id字段,继续最终,最后终于在TableMetaDataContext#createInsertString(java.lang.String[])方法里面找到,关键的代码片段如下:

  1. for (String columnName : this.getTableColumns()) {
  2.             // 这里将SimpleJdbcInsert#usingGeneratedKeyColumns方法中所设置的字段去除了
  3.             if (!keys.contains(columnName.toUpperCase())) {
  4.                 columnCount++;
  5.                 if (columnCount > 1) {
  6.                     insertStatement.append(", ");
  7.                 }
  8.                 insertStatement.append(columnName);
  9.             }
  10.         }

 

看到这里,我也猛然恍然大悟了。既然在INSERT INTO语句中设置了UUID的值,那这里就不需要再使用KeyHolder进行返回了,直接获取就是了。这也是为什么KeyHolder中的getKey()方法的返回类型是Number的原因了,因为通常来说需要Spring返回的就是插入数据库中的自增类型的主键值。

0
0
分享到:
评论

相关推荐

    Python3 操作 MySQL 插入一条数据并返回主键 id的实例

    在需要进行表与表之间的关联时,我们通常需要插入数据后立即得到这个数据的主键id以供关联使用。在Java的MyBatis框架中,可以使用标签在insert方法前通过执行SELECT LAST_INSERT_ID()来获取最新插入行的id,这与...

    mybatis 批量插入返回主键

    只提供代码,自己去下载相关jar包谢谢只提供代码,自己去下载相关jar包谢谢只提供代码,自己去下载相关jar包谢谢只提供代码,自己去下载相关jar包谢谢只提供代码,自己去下载相关jar包谢谢

    jdbc保存对象返回一个主键

    3. **JdbcTemplate**:Spring框架中的一个类,用于简化JDBC的使用,提供了一组方便的方法来处理数据库操作。 #### 三、代码解析 假设我们有一个`MessageText`对象,需要将其保存到数据库,并希望在保存后能够获取...

    MybatisPlus中插入数据获取主键值示例代码

    这里需要注意的是,只有当主键是自增类型时,`insert`方法才会返回主键值。如果主键不是自增的,那么`getId()`方法会返回`null`。此外,对于非自增主键,你可能需要使用其他方法,如雪花算法等生成全局唯一的ID。 ...

    详解mybatis plus使用insert没有返回主键的处理

    在使用 MP 插入数据时,对于设置了自增主键的字段,通常 MP 会自动处理主键的生成和返回。这里以 `UserInfo` 实体类为例,`@TableId` 注解用于指定主键字段 `userId`,并且类型设置为 `IdType.AUTO`,表明这是个自增...

    数据库主键的五种设计方法

    数据库主键设计的五种方法 数据库主键设计是数据库设计中一个非常重要的环节,好的主键设计可以提高数据库的性能和可扩展性。...在选择主键设计方法时,我们需要考虑项目的实际情况和需求,选择最适合的方法。

    oracle数据库主键自增并且返回主键值

    一、创建序列 1.1、直接在PLSQL中设置 1.2、命令创建 create sequence seq_users ##创建序列seq_users increment by 1 ## 步长,每次加1 start with 1 ##从1开始 minvalue 1 ##最小值 maxvalue 9999999 ##最大值 ...

    hibernate联合主键全攻略

    在Java端,我们需要创建一个对应于联合主键的实体类,如`UsersPK`,通常会包含与`&lt;composite-id&gt;`中定义的字段相对应的属性和getter/setter方法。例如: ```java public class UsersPK implements Serializable { ...

    hibernate使用主键关联的一对一关系

    1. **共享主键**:这是通过让两个实体类共享同一个主键字段来实现一对一关系的方法。这通常意味着一个实体类的主键同时是另一个实体类的外键。在XML映射文件中,可以使用`&lt;one-to-one&gt;`标签来声明这种关系: ```xml...

    使用ODI处理没有主键的表全攻略

    在数据集成和ETL(提取、转换、加载)过程中,Oracle Data Integrator (ODI) 是一个强大的工具,但在处理没有主键的表时,ODI面临一些挑战。主键是数据库中用于唯一标识记录的关键字段,但在某些业务系统中,如...

    Mybatis批量插入数据返回主键的实现

    Mybatis是当前最流行的持久层框架之一,它提供了强大的批量插入功能,但是在批量插入数据时如何返回主键是一个常见的问题本文将详细介绍Mybatis批量插入数据返回主键的实现。 在Mybatis中,批量插入数据可以通过...

    jdbc 插入记录并返回自增主键值

    `executeUpdate()`方法执行插入操作,而`getGeneratedKeys()`则返回一个`ResultSet`,其中包含由数据库生成的所有键。由于我们只插入了一条记录,所以`ResultSet`通常只有一个行,可以通过`rs.getInt(1)`获取第一列...

    MyBatis在insert插入操作时返回主键ID的配置(推荐)

    其中,在 insert 插入操作时返回主键 ID 是一个非常重要的功能,特别是在需要将插入的数据 ID 用于后续操作或作为外键时。本文将详细介绍 MyBatis 在 insert 插入操作时返回主键 ID 的配置,包括 MySQL 和 Oracle 两...

    Hibernate一对多使用非主键关联设置

    `Department`表有一个非主键字段`department_code`,`Employee`表有一个字段`department_code`,用于表示员工所属的部门。在Hibernate中,我们可以这样设置: 1. 定义实体类: - `Department`类: ```java ...

    Spring的JdbcTemplate插入操作返回主键ID的方法 - - ITeye技术网站.htm

    Spring的JdbcTemplate插入操作返回主键ID的方法 - - ITeye技术网站

    MyBatis+MySQL 返回插入的主键ID的方法

    首先,我们需要在MyBatis的Mapper接口中定义一个插入并返回主键ID的方法。这里我们以一个`UserDao`接口为例,定义一个`insertAndGetId`方法: ```java public interface UserDao { public int insertAndGetId(User...

    hibernate复合主键配置和使用

    首先,我们需要创建一个表示复合主键的类,该类需要被`@Embeddable`注解标记。例如,假设我们有用户地址表,其中主键由用户ID和地址ID组成: ```java @Embeddable public class AddressId implements Serializable ...

    ORACLE自增主键设置方法

    使用`SYS_GUID()`函数时需要注意的是,生成的值长度固定为32位,这可能不适合所有类型的主键需求。 #### 五、总结 通过上述步骤,我们可以有效地在Oracle数据库中设置自增主键。这种方式不仅简化了主键的管理和...

    Hibernate复合主键

    Hibernate复合主键是指在 Hibernate 框架中使用复合主键来唯一标识一个实体。复合主键是指由多个字段组成的主键,用于唯一标识一个实体。在本例中,我们将通过一个简单的复合主键的做关联类的例子来说明 Hibernate ...

Global site tag (gtag.js) - Google Analytics