NHibernate Id生成器与MySQL自增主键映射配置疑问
嘿,这个问题我做项目的时候也纠结过,其实核心点很明确:要不要移除数据库列的auto-increment,完全取决于你选的NHibernate主键生成器(generator)策略,不是所有情况都要删的,咱们分情况说清楚:
1. 用identity或native生成器:必须保留auto-increment
这是MySQL环境下最常用的两种主键生成策略:
identity:专门对应MySQL的auto-increment机制,NHibernate会让数据库自动生成主键值,然后把生成的ID回写到你的实体对象里。native:NHibernate会自动适配数据库类型,在MySQL下它会自动切换成identity模式。
这种情况下,数据库列的auto-increment绝对不能移除,否则NHibernate会抛出主键生成失败的异常——因为它完全依赖数据库的自增逻辑来生成ID。
举个映射示例:
<!-- XML映射文件 --> <id name="Id" column="user_id"> <generator class="identity"/> </id>
或者Fluent NHibernate的写法:
// Fluent NHibernate配置 Id(x => x.Id).Column("user_id").GeneratedBy.Identity();
2. 用assigned生成器:必须移除auto-increment
如果你选择自己手动给实体设置主键值(比如业务有特定的ID规则),就要用assigned生成器。这时候数据库列的auto-increment必须删掉,否则你手动设置的ID会被数据库的自增逻辑覆盖,要么导致主键冲突,要么得到的ID不是你预期的值。
3. 用hilo、uuid.hex等NHibernate自主生成的策略:建议移除auto-increment
这类生成器是NHibernate自己在应用层生成主键值,不需要数据库介入。比如hilo用高低位算法生成ID,uuid.hex生成唯一字符串ID。
这种情况下,数据库列的auto-increment完全没用,留着反而可能出问题(比如不小心触发数据库自增),所以最好移除,把列改成普通的INT/VARCHAR类型即可。
4. 用sequence生成器(仅MySQL 8.0+支持):移除auto-increment并创建序列
MySQL 8.0开始支持序列对象,如果你想用sequence生成器,需要先在数据库创建对应的序列,然后移除列的auto-increment属性,让NHibernate通过序列获取主键值。不过这种在MySQL里用得不多,大部分场景还是identity更顺手。
小提示
如果拿不准,可以开启NHibernate的SQL日志,看看它在插入数据时是怎么处理主键的——如果日志里能看到数据库自增的ID被回显,那就是依赖auto-increment;如果是直接把生成好的ID写入数据库,那就要确保auto-increment已经移除。
内容的提问来源于stack exchange,提问作者Soul Reaver




