hbm.xml文件须与实体类同包且命名一致,如com.example.user类对应user.hbm.xml;class标签name需全限定名、table指定表名;id generator需按数据库选策略;Property type影响jdbc绑定。

hbm.xml 文件必须和实体类同包且命名一致
旧版 hibernate 用 hbm.xml 做映射,不是随便放哪都行。它得和对应实体类在同一个包路径下,文件名也得严格匹配:比如类是 com.example.User,那 XML 就得叫 User.hbm.xml,放在 src/main/Resources/com/example/(或 classpath 对应位置)。
常见错误现象:org.hibernate.MappingNotFoundException: resource: User.hbm.xml not found,八成是路径或名字差了半个字符;ide 里看着在同目录,但编译后没进 classes,也常导致这个错。
- 检查
build.gradle或pom.xml是否把*.hbm.xml纳入资源拷贝(maven 默认不处理非.xml在 resources 下的文件?错——它会,但如果你放 src/java 里就真不会) - 用 IDE 的 “Show in Explorer” 确认编译后 XML 确实出现在 target/classes 对应路径
- 别用中文或空格命名文件,
User Info.hbm.xml这种直接报解析失败
标签里的 name 和 table 属性不能省略
<class></class> 是根映射元素,name 必须写全限定类名(如 com.example.User),table 得写数据库表名(如 user_info)。漏掉 name 会导致 Hibernate 根本不知道映射到谁;漏 table 则默认用类名小写当表名(user),跟实际不符就查不到数据。
使用场景:老系统表名带下划线、类名用驼峰,比如数据库是 order_item,类叫 OrderItem,那就得显式写 table="order_item",不能指望 Hibernate 自动转换。
-
schema和catalog属性按需加,跨 schema 查询时缺一不可 -
dynamic-insert="true"和dynamic-update="true"可减少 sql 冗余字段,但会让日志更难读,调试期建议关掉 - 别在
<class></class>里写lazy="false"—— 这属性只对关联映射(<many-to-one></many-to-one>等)有效,放这儿会被忽略
id 映射必须配 ,native 不等于 auto
旧版里 <id></id> 下的 <generator class="native"></generator> 是最常用写法,但它不是“自动选”,而是按方言动态选策略:mysql 用 identity,oracle 用 sequence,HSQLDB 用 identity。如果数据库不支持对应策略(比如 Oracle 没建 sequence),启动就抛 IdentifierGenerationException。
性能影响:用 increment 看似简单,但在集群或高并发下会生成重复 ID,绝对别在线上用;uuid 虽安全,但字符串主键影响索引效率,且 MySQL 里 char(32) 比 BIGINT 慢不少。
- 明确用
identity前,先确认数据库是否支持自增(postgresql 要用serial配合identity) - Oracle 必须配
<param name="sequence">SEQ_USER,否则 fallback 到hilo,可能产生间隙 ID -
<generator class="assigned"></generator>表示手动赋值,此时代码里必须显式设 ID,否则插入时报空值
property 映射的 type 属性常被忽略但很关键
<property></property> 的 type 不只是类型提示,它决定 Hibernate 怎么做 JDBC 绑定和结果集读取。比如 Java 的 java.time.LocalDate,不写 type="localDate"(Hibernate 5+)或 type="date"(旧版),就会当成 java.util.Date 处理,查出来时秒数乱套,甚至抛 ClassCastException。
兼容性影响:Hibernate 3.x 默认不识别 JSR-310 类型,必须用第三方方言(如 hibernate-types)或自己写 UserType;而 type="yes_no" 这种内置类型,能把布尔值存成 'Y'/'N' 字符,比 bit 更兼容老数据库。
- 字符串字段加
Length="50",不然默认长度是 255,可能触发 MySQL 的sql_mode=STRICT_TRANS_TABLES报错 -
not-NULL="true"只影响 DDL 生成(create-table),不影响运行时校验,别以为加了它就能防空插入 -
access="field"表示跳过 getter/setter 直接读写字段,适合有复杂逻辑的 setter 场景,但字段名拼错就静默失败
XML 映射真正麻烦的不是语法,而是每个属性背后都绑着方言、驱动、JDBC 类型、甚至数据库版本。改一行 type,可能让本地跑通的代码在测试环境连不上字段。