タイトル: net.sf.hibernate.MappingException: Error reading resource
SEOタイトル: Hibernate MappingException Error reading resource の原因と対処
| この記事の要点 |
|
エラー全文
net.sf.hibernate.MappingException: Error reading resource: com/example/model/User.hbm.xml
at net.sf.hibernate.cfg.Configuration.addResource(Configuration.java:380)
at net.sf.hibernate.cfg.Configuration.addClass(Configuration.java:419)
...
Caused by: org.dom4j.DocumentException: Error on line 12 of document : ...
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
...
パッケージ名が net.sf.hibernate なら Hibernate 2.x 系(2005 年頃まで)。org.hibernate なら 3.x 以降です。古いプロジェクトの保守でよく遭遇します。
原因の切り分け
| 原因 | 確認方法 | 対処 |
|---|---|---|
| hbm.xml が classpath に無い | jar 解凍して User.hbm.xml の有無 | src/main/resources に移動 (対処1) |
| パス指定誤り | hibernate.cfg.xml の <mapping> | パッケージ階層を / 区切りで (対処2) |
| XML 構文エラー | Caused by に DocumentException | XML エディタで検証 (対処3) |
| クラス名 mismatch | <class name="..."> | 完全修飾名で記述 (対処4) |
| DTD/XSD バージョン不一致 | <!DOCTYPE> 宣言 | 使用 Hibernate 版に揃える (対処5) |
| Maven の resources プラグイン設定 | target/classes に hbm.xml が無い | pom.xml 修正 (対処6) |
対処1: hbm.xml を classpath に置く
src/
└ main/
├ java/
│ └ com/example/model/User.java
└ resources/ <- ★ ここに置く
├ hibernate.cfg.xml
└ com/example/model/User.hbm.xml <- パッケージ階層を作る
ビルド後 (target/classes 配下):
target/classes/
├ com/example/model/User.class
├ com/example/model/User.hbm.xml <- 同じ階層に並ぶこと
└ hibernate.cfg.xml
対処2: hibernate.cfg.xml で正しく指定
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</property>
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">secret</property>
<!-- ★ パッケージは / 区切り、拡張子 .hbm.xml -->
<mapping resource="com/example/model/User.hbm.xml" />
<mapping resource="com/example/model/Order.hbm.xml" />
<!-- アノテーション併用なら -->
<mapping class="com.example.model.Product" />
</session-factory>
</hibernate-configuration>
対処3: hbm.xml の構文確認
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.example.model.User" table="users">
<id name="id" type="long" column="id">
<generator class="identity" />
</id>
<property name="name" type="string" column="name" length="100" not-null="true" />
<property name="email" type="string" column="email" length="200" />
<property name="createdAt" type="timestamp" column="created_at" />
<many-to-one name="organization" column="org_id"
class="com.example.model.Organization" />
<set name="orders" cascade="all" lazy="true">
<key column="user_id" />
<one-to-many class="com.example.model.Order" />
</set>
</class>
</hibernate-mapping>
典型的な XML 構文ミス: 閉じタグ漏れ / 属性値のクォート漏れ / 全角スペース混入 / BOM 付き UTF-8。IDE の XML エディタで赤線が出ない状態にしてください。
対処4: クラス名は完全修飾で
<!-- ❌ NG: パッケージ抜け -->
<class name="User" table="users">...</class>
<!-- ✅ OK: 完全修飾名 -->
<class name="com.example.model.User" table="users">...</class>
<!-- ✅ OK: hbm.xml の親要素で package 宣言してから短縮形 -->
<hibernate-mapping package="com.example.model">
<class name="User" table="users">...</class>
</hibernate-mapping>
対処5: DTD バージョン不一致
| Hibernate 版 | パッケージ | DTD |
|---|---|---|
| 2.x | net.sf.hibernate | hibernate-mapping-2.0.dtd |
| 3.x | org.hibernate | hibernate-mapping-3.0.dtd |
| 4.x - 6.x | org.hibernate | hibernate-mapping-3.0.dtd (継続) |
古い hbm.xml をそのまま新しい Hibernate に持ち込むと、DTD 不一致や非推奨タグでエラーになります。パッケージ移動が必須: net.sf.hibernate.* → org.hibernate.* を全置換。
対処6: Maven で hbm.xml を成果物に含める
<!-- pom.xml -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
<!-- Java ソースと同じ階層に hbm.xml がある場合 -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.hbm.xml</include>
</includes>
</resource>
</resources>
</build>
JPA アノテーション (推奨)
新規開発では xml なし の JPA アノテーションが標準です:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 100)
private String name;
@Column(length = 200)
private String email;
@Column(name = "created_at")
private LocalDateTime createdAt;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "org_id")
private Organization organization;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Order> orders = new HashSet<>();
}
Spring Boot なら @SpringBootApplication + @EnableJpaRepositories で自動スキャンされ、hibernate.cfg.xml も hbm.xml も不要です。
Hibernate 5 → 6 移行の注意
- パッケージ:
javax.persistence.*→jakarta.persistence.* - 古い Dialect クラス (
MySQL5Dialect等) は削除 →MySQLDialect1 つに統合 - カスタム UserType API が刷新 →
UserType<T>インターフェース - Bytecode enhancement のデフォルトが変更
- 結果として 古い hbm.xml はそのままでは動かない → JPA に移行 or hibernate-types 利用
FAQ
Q: Eclipse からは動くが mvn package すると失敗する
A: Eclipse が src/main/java の hbm.xml を classpath に含めてしまっているケース。Maven 側で resources プラグインに含めるか、resources ディレクトリに移動する。
Q: 「The reference to entity must end with the ";" delimiter」と出る
A: hbm.xml に & を生で書いている可能性。&amp; にエスケープ。
Q: classpath に hbm.xml はあるのに読まれない
A: ClassLoader の問題。複数 jar 同梱で同名 hbm.xml が衝突しているとどちらが読まれるか不定。jar -tf で確認し名前を一意化。