java访问sql 2008 检索自动生成的键,获得 IDENTITY 值的方法

本文介绍使用PreparedStatement和Statement.RETURN_GENERATED_KEYS方法获取SQL Server 2008中插入操作后自动生成的主键值的方法,避免使用SCOPE_IDENTITY()可能带来的错误。

 

访问sql2008,insert后获得自动生成的键,用sql2000处理方法SELECT SCOPE_IDENTITY() 可能会出错

 

可以用Statement 类的 getGeneratedKeys 方法返回包含一列,列名为GENERATED_KEYS的结果集,内容为自动生成的键


1、设置PreparedStatement(推荐)

 

PreparedStatement  ps = conn.prepareStatement(...., Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();

 

 

2、执行executeUpdate时加参数Statement.RETURN_GENERATED_KEYS

 

stmt.executeUpdate("insert into ... ",Statement.RETURN_GENERATED_KEYS);
 ResultSet rs=stmt.getGeneratedKeys();

### 如何在 SQL 中实现 `INSERT` 操作时自动生成唯一主 ID #### 使用数据库内置功能生成主 许多关系型数据库提供了内置的功能用于生成唯一的主字段。例如,在 MySQLSQL Server 中可以使用 `AUTO_INCREMENT` 或者 `IDENTITY` 属性来定义列,使其能够自动增加并保持唯一性。 对于 MySQL 数据库而言,可以通过设置某一列为 `PRIMARY KEY AUTO_INCREMENT` 来实现这一目标[^1]: ```sql CREATE TABLE example_table ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL ); ``` 当向上述表格插入数据时无需指定 `id` ,数据库会自动为其分配一个递增的整数作为主。 #### 利用 MyBatis 插件机制实现主生成逻辑 如果项目中采用了 MyBatis 作为持久层框架,则还可以借助插件的方式来自定义主生成策略。具体来说就是创建一个拦截器类继承 `org.apache.ibatis.plugin.Interceptor` 接口,并重写其中的方法完成对原始对象的操作前后的处理工作[^2]。 下面是一个简单的例子展示了如何通过编写自定义拦截器来为新增记录动态填充 UUID 类型字符串形式的主: ```java @Intercepts(value={ @Signature(type = Executor.class, method="update", args={MappedStatement.class, Object.class}) }) public class AutoIdInterceptor implements Interceptor { private static final Logger logger = LoggerFactory.getLogger(AutoIdInterceptor.class); public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStmt = (MappedStatement)invocation.getArgs()[0]; String sqlCommandType = mappedStmt.getSqlCommandType().name(); if ("INSERT".equalsIgnoreCase(sqlCommandType)){ Object parameterObject = invocation.getArgs()[1]; MetaObject metaParamObj = SystemMetaObject.forObject(parameterObject); Field[] fields = parameterObject.getClass().getDeclaredFields(); boolean hasPrimaryKeyField=false; for(Field f :fields){ Column column=f.getDeclaredAnnotation(Column.class); Id id=f.getDeclaredAnnotation(Id.class); if(id!=null && !metaParamObj.hasGetter(f.getName())){ String generatedValue=UUID.randomUUID().toString(); metaParamObj.setValue(f.getName(),generatedValue ); break; } } } return invocation.proceed(); } } ``` 此代码片段中的核心部分在于遍历参数实体的所有属性查找标记有 JPA 注解 `@Id` 的成员变量;一旦发现符合条件的目标字段尚未被赋初则随机生成一段独一无二的文字串赋予之。 #### 获取刚插入行所产生的主 除了让 DBMS 自动计算外之外有时我们也希望能够在应用程序层面捕获到刚刚成功提交的新纪录对应的主编号以便进一步操作关联子项等内容。此时可利用 JDBC API 提供的相关方法达成目的[^3]: ```java PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO orders(order_date,customer_id,status)" + "VALUES(CURDATE(),?,?)", Statement.RETURN_GENERATED_KEYS ); pstmt.setInt(1, customerId); pstmt.setString(2,"PENDING"); int affectedRows=pstmt.executeUpdate(); if(affectedRows==0 ){ throw new SQLException("Creating user failed,no rows affected."); } ResultSet rs=pstmt.getGeneratedKeys(); long orderId=-1; if(rs.next()){ orderId=rs.getLong(1); }else{ throw new SQLException("Cannot obtain auto-generated key"); } System.out.println("New Order Created With ID:"+orderId); ``` 上面这段程序演示了怎样调用 PreparedStatement 对象上的 getGeneratedKeys() 函数检索最近一次执行 DML 指令之后产生的新条目所携带的关字信息。 #### 定义非连续字符类型的主约束条件 最后得注意的一点是在设计模式允许的情况下也可以考虑采用固定长度或者变长但是具备一定规律性的文本序列充当主角色而不是单纯依赖于数字累加方式构建索引结构。比如下述范例就规定了一个名为 `id` 的字段接受最多一百个字母组成的任意组合并且附加说明该栏位需满足唯一性校验标准[^4]: ```sql CREATE TABLE users ( `id` varchar(100) COLLATE utf8_estonian_ci NOT NULL COMMENT '唯一不重复', username VARCHAR(50), password_hash CHAR(60), -- Assuming bcrypt hash length is fixed at 60 chars. email_address TEXT UNIQUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT pk_user PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ; ``` 这样做的好处是可以有效避免因频繁更新而引发的数据迁移成本同时也便于跨平台移植以及与其他系统的集成对接等工作场景下的应用需求匹配问题解决思路探讨.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值