◀ 3.

Hibernate MappingException: No persister for エラー対処

▶
この記事の要点
  • MappingException: No persister for ~ は「そのクラスは Hibernate に登録されていない」という意味
  • 最も多い原因は、設定ファイルに <mapping resource="~.hbm.xml"/> の記述が抜けていること
  • hbm.xml がクラスパス上にない、パスの書き間違い、渡しているオブジェクトのクラス違いでも起きる
  • アノテーション方式では @Entity の付け忘れ・登録漏れ・import 違い(javax と jakarta の混在など)が原因になる
  • net.sf.hibernate は Hibernate 2 系のパッケージ。新しい版では「Unknown entity」など別の文言になる

エラー内容

net.sf.hibernate.MappingException: No persister for ~

「~」の部分には、session.save() や session.load() などに渡したオブジェクトのクラス名(例: com.example.bean.User)が入ります。このクラス名が、原因調査の一番の手がかりです。

このエラーの意味

Hibernate は、起動時に読み込んだマッピング定義から「クラスごとの永続化担当オブジェクト(persister)」を作っておき、保存や取得のたびにクラス名で persister を探します。渡されたクラスの persister が見つからない=そのクラスのマッピングが Hibernate に登録されていないときに、このエラーが出ます。

net.sf.hibernate で始まるのは Hibernate 2 系です。Hibernate 3 以降はパッケージが org.hibernate に変わり、同じ状況でも MappingException: Unknown entity などの文言になります(さらに新しい版では「Unable to locate persister」といった表現もあります)。原因の考え方は共通です。

主な原因

原因確認するところ
設定ファイルに mapping の記述がないhibernate.cfg.xml に対象クラスの <mapping resource="..."/> があるか
hbm.xml のパスが間違っている / ビルド成果物に含まれていないresource のパス(パッケージ区切りは /)、WAR や jar の中に hbm.xml が入っているか
hbm.xml の class name と実際のクラスが違うパッケージ名を含めた完全修飾名が一致しているか
マッピングしていないクラスを渡しているエラーに出たクラス名が想定どおりか(List や DTO、未マッピングのサブクラスを渡していないか)
アノテーション方式での登録漏れ@Entity の有無、<mapping class="..."/> やパッケージスキャンの対象に入っているか

なお、カラムの型と Java フィールドの型の不一致は、通常このエラーではなく、値の取得・設定時の別の例外(型変換エラーなど)として現れます。まずは「登録されているか」を疑うのが近道です。

対処法

1. 設定ファイルに mapping を追加する

Hibernate の設定ファイルに、使用する bean のマッピングファイルを列挙します。クラスを追加したのに、ここへの追記を忘れるのが典型的なパターンです。

<hibernate-configuration>
  <session-factory>
    <!-- 接続設定などは省略 -->
    <mapping resource="com/example/bean/User.hbm.xml"/>
    <mapping resource="com/example/bean/Dept.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

もちろん、個別の bean のマッピングファイル(~.hbm.xml)自体の定義も必要です。

<hibernate-mapping>
  <class name="com.example.bean.User" table="user">
    <id name="userId" column="user_id">
      <generator class="assigned"/>
    </id>
    <property name="userName" column="user_name"/>
  </class>
</hibernate-mapping>

2. コードで登録している場合

設定ファイルではなく Java コードで Configuration を組み立てている場合は、そこにクラスやリソースを追加します。

Configuration cfg = new Configuration()
        .configure()                       // hibernate.cfg.xml を読む
        .addResource("com/example/bean/User.hbm.xml");
// 同じパッケージに User.hbm.xml を置いているなら
// cfg.addClass(com.example.bean.User.class); でもよい

3. アノテーション方式の場合(Hibernate 3 以降)

  • エンティティクラスに @Entity が付いているか確認します
  • @Entity の import が JPA のもの(javax.persistence.Entity、Hibernate 6 以降は jakarta.persistence.Entity)になっているか確認します。古い Hibernate 独自の org.hibernate.annotations.Entity だけでは登録されません。使っている Hibernate のバージョンと javax / jakarta が食い違っていても認識されません
  • <mapping class="com.example.bean.User"/> の追加、または Spring の packagesToScan などスキャン対象パッケージに含まれているかを確認します

確認方法

  1. エラーに表示されたクラス名を控え、設定ファイル・hbm.xml の class name と一字一句比べる
  2. ビルド後の出力先(WEB-INF/classes や jar の中)に hbm.xml が含まれているか確認する。Maven では hbm.xml を src/main/resources 側に置かないとコピーされないことがある
  3. 起動ログに、マッピングを読み込んだクラスの一覧が出ているか確認する(出ていなければ Hibernate のログレベルを INFO や DEBUG にして確認する)
  4. 修正後、アプリケーションを再起動して SessionFactory を作り直す(ホットデプロイでは反映されない場合がある)

関連

Post Share
子ページ

子ページはありません

同階層のページ
  1. ids for this class must be manually assigned before calling save()
  2. Number of positional parameter types (1 does not match number of positional parameters (2)
  3. net.sf.hibernate.MappingException: No persister for ~
  4. net.sf.hibernate.QueryException: unexpected token: as [~]
  5. net.sf.hibernate.MappingException: Error reading resource
  6. IllegalArgumentException occurred while calling setter of