mybatis配置oracle的主键自增长

mysql、sqlserver等数据库本身带有主键自增长像auto_increment的功能可以直接使用

useGeneratedKeys=”true”来实现,比如下面的配置

<insert id=”add” useGeneratedKeys=”true” keyProperty=”id” parameterType=”Auth”>
insert into s_user_auth (id,user_id, user_name) values(#{id},#{userid},#{username})
</insert>

而oracle则不行,oracle主键自增长是通过sequence实现的,所以这种方式就不可以了,需要使用:

1.先通过sequence查出来id,再insert

<insert id=”add” useGeneratedKeys=”false” keyProperty=”id” parameterType=”Auth”>
<selectKey resultType=”String”  keyProperty=”id” order=”BEFORE”>
select yoursequence.nextval as id from dual
</selectKey>
insert into s_user_auth (id,user_id, user_name) values(#{id},#{userid},#{username})
</insert>

2.直接insertsequence.nextval,如下

<insert id=”add” useGeneratedKeys=”false” keyProperty=”id” parameterType=”Auth”>
insert into s_user_auth (id,user_id, user_name) values(yoursequence.nextval,#{userid},#{username})
</insert>
<think>我们正在解决MyBatis自动生成主键失败的问题。根据引用内容,我们可以从以下几个方面分析原因并提供解决方案: 1. **数据库支持与配置检查**: - 确认数据库是否支持自增主键(如MySQL的AUTO_INCREMENT,PostgreSQL的SERIAL)。如果不支持(如Oracle),则不能使用`useGeneratedKeys`,而需要使用`<selectKey>`标签(引用[2])。 - 在支持自增主键的数据库中,检查表的主键列是否确实设置了自增属性(如MySQL的AUTO_INCREMENT)。 2. **MyBatis配置检查**: - 在Mapper XML文件中,确保`<insert>`标签正确设置了`useGeneratedKeys="true"`和`keyProperty`属性(如`keyProperty="id"`),且`keyProperty`的值与Java对象的主键属性名一致(引用[2])。 - 如果数据库不支持自增主键(如Oracle),需使用`<selectKey>`标签手动生成主键(引用[2]示例)。 3. **代码逻辑检查**: - 插入操作后,是否通过Java对象获取主键值(如`user.getId()`),而不是试图从SQL结果中获取(因为插入操作返回的是影响行数,而非主键值)。 4. **MyBatis Plus的特殊配置**: - 如果使用MyBatis Plus,可以通过`@TableId`注解指定主键生成策略(引用[1])。例如: ```java public class User { @TableId(type = IdType.AUTO) // 使用数据库自增 private Long id; // 其他属性... } ``` - 注意:`IdType.AUTO`要求数据库主键列设置为自增;`IdType.ASSIGN_ID`(默认)使用雪花算法生成主键(不依赖数据库自增)。 5. **数据库连接配置**: - 检查JDBC URL是否包含参数`useAffectedRows=true`(MySQL),这可能导致主键无法正确回填。建议移除该参数或设置为`false`。 6. **事务与连接问题**: - 确保插入操作在同一个事务中完成,且未提前关闭数据库连接(否则可能无法获取生成的主键)。 ### 解决方案步骤 #### 情况1:使用支持自增主键的数据库(如MySQL) 1. **数据库表检查**:确保主键列设置了`AUTO_INCREMENT`(MySQL)或类似属性。 2. **Mapper XML配置**: ```xml <insert id="insertUser" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user (name, age) VALUES (#{name}, #{age}) </insert> ``` - 注意:SQL中**不包含主键列**(如`id`)。 3. **Java代码**: ```java User user = new User(); user.setName("John"); userMapper.insertUser(user); // 执行插入 System.out.println(user.getId()); // 获取主键 ``` #### 情况2:使用不支持自增主键的数据库(如Oracle) 使用`<selectKey>`标签生成主键(引用[2]示例): ```xml <insert id="addUser" parameterType="User"> <selectKey keyProperty="id" resultType="Integer" order="BEFORE"> SELECT your_sequence.NEXTVAL AS id FROM DUAL </selectKey> INSERT INTO t_user (id, username) VALUES (#{id}, #{username}) </insert> ``` - `order="BEFORE"`:在插入前获取主键值(适用于Oracle序列)。 - `keyProperty="id"`:将生成的主键值赋给Java对象的`id`属性。 #### 情况3:使用MyBatis Plus 1. 实体类添加注解: ```java public class User { @TableId(type = IdType.AUTO) // 数据库自增 private Long id; // 其他属性... } ``` 2. 如果使用雪花算法(默认`IdType.ASSIGN_ID`),无需数据库自增,但需确保主键类型为`Long`或`String`。 ### 常见错误排查 - **主键值未回填**: - 检查`keyProperty`是否拼写错误(如Java对象属性名是`userId`,但配置`keyProperty="id"`)。 - 检查JDBC驱动版本(过低版本可能不支持`getGeneratedKeys`)。 - **Oracle主键重复**: - 确保`<selectKey>`中的序列调用正确(如`your_sequence.NEXTVAL`)。 - **MyBatis Plus主键策略冲突**: - 避免同时使用XML配置和`@TableId`注解(优先使用注解配置)。 通过以上步骤,可解决大部分MyBatis自动生成主键失败的问题。若仍无法解决,请检查数据库连接是否正常,以及是否有拦截器修改了SQL或结果。 §§相关问题§§ 1. 如何为Oracle数据库配置MyBatis序列主键生成? 2. MyBatis Plus中`@TableId`注解的常用主键策略有哪些? 3. MyBatis插入后获取主键值为null的可能原因有哪些? [^1]: MyBatis-Plus主键生成策略。MyBatis-Plus 主键生成策略中,最常用的是IdType.AUTO,表示主键的生成是由 数据库的自增功能 控制的,前提:数据库的主键列必须设置为 AUTO_INCREMENT。 MyBatis-Plus 提供了内置的主键生成策略,可以在不改动业务代码的前提下自动生成主键值,而无需依赖数据库的自增主键。以下是解决方法和配置方式: (1)IdType.ASSIGN_ID(默认雪花算法) [^2]: MyBatis插入操作:生成主键。2.如果使用的数据库不支持主键自动增长(如Oracle ),或者支持增长的数据库取消了主键自增的规则时,可以使用MyBatis 提供的另一种方式来自定义生成主键,具体配置示例如下。 <insert id="addUser" parameterType="com.lesour.po.User"> <selectKey keyProperty="id" resultType="Integer" order="BEFORE"> select if(max(id) is null , 1 , max(id) +1) as newld from t customer </selectKey> insert into t_user( id, username , jobs , phone) values(#{id} , #{username} , #{jobs} , #{phone}) </insert> [^3]: 解决mybatis generator生成没有根据主键的select,update和delete问题。这个是解决另外一个坑的方法 <!-- 只允许生成当前数据库的表 --> <property name="nullCatalogMeansCurrent" value="true"/></think>### MyBatis 自动生成主键失败的原因及解决方案 当 MyBatis 自动生成主键失败时,通常由以下原因导致。请根据具体情况逐步排查: #### 原因一:数据库不支持自增主键(如 Oracle) **现象**:使用 `useGeneratedKeys="true"` 配置无效 **解决方案**:使用 `<selectKey>` 标签手动生成主键 ```xml <insert id="addUser" parameterType="User"> <!-- 针对 Oracle序列生成主键 --> <selectKey keyProperty="id" resultType="Long" order="BEFORE"> SELECT your_sequence.NEXTVAL AS id FROM DUAL </selectKey> INSERT INTO t_user(id, username) VALUES(#{id}, #{username}) </insert> ``` **关键参数**: - `order="BEFORE"`:在插入前生成主键Oracle 常用) - `keyProperty="id"`:指定存储主键的 Java 属性[^2] #### 原因二:数据库自增配置未生效 **现象**:MySQL 等数据库返回的主键为 0 或 null **检查步骤**: 1. 确认数据库表主键已设置 `AUTO_INCREMENT`(MySQL)或 `SERIAL`(PostgreSQL) 2. 验证 JDBC URL 包含参数:`useSSL=false&useUnicode=true&characterEncoding=UTF-8&useAffectedRows=true` 3. 检查数据库用户是否有操作序列的权限(Oracle) #### 原因三:MyBatis 配置错误 **常见错误**: 1. `keyProperty` 名称与实体类属性不匹配 ```xml <!-- 错误示例:Java 属性名为 userId,但配置为 id --> <insert useGeneratedKeys="true" keyProperty="id">...</insert> ``` **修复**:确保 `keyProperty` 值等于实体类的主键字段名 2. 忘记在 SQL 中排除主键列 ```sql <!-- 错误示例:包含自增主键列 --> INSERT INTO t_user(id, name) VALUES(#{id}, #{name}) ❌ <!-- 正确写法:省略主键列 --> INSERT INTO t_user(name) VALUES(#{name}) ✅ ``` #### 原因四:MyBatis Plus 注解配置问题 **现象**:使用 `@TableId` 注解但主键未生成 **解决方案**: ```java public class User { // 明确指定主键策略 @TableId(type = IdType.AUTO) // 数据库自增 private Long id; // 或使用雪花算法 // @TableId(type = IdType.ASSIGN_ID) } ``` **主键策略说明**: - `IdType.AUTO`:依赖数据库自增(需数据库支持) - `IdType.ASSIGN_ID`:默认策略,使用雪花算法(不依赖数据库)[^1] #### 原因五:事务或连接问题 **现象**:主键在事务提交前不可用 **解决方案**: ```java // 确保在事务提交后获取主键 User user = new User(); userMapper.insert(user); System.out.println("生成的主键:" + user.getId()); // 立即可用 ``` **注意**:MyBatis 会在执行插入后立即将主键值注入对象,无需等待事务提交 #### 终极排查清单 1. ✅ 检查数据库是否支持自增主键 2. ✅ 验证 `keyProperty` 与实体类属性名一致 3. ✅ 确保 SQL 未包含自增主键列 4. ✅ 查看 JDBC 驱动版本(推荐 MySQL Connector/J 8.0+) 5. ✅ 测试数据库连接是否正常 6. ✅ 检查是否有拦截器修改了 SQL 或结果 > **特殊场景处理**:分库分表环境下,建议使用 `IdType.ASSIGN_ID`(雪花算法)避免主键冲突[^1]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值