0

注釈を使用してスキーマを設定しようとすると、Hibernate でイライラするような動作が発生します。他のいくつかの型と 1 対多の関係を持つエンティティがあるとします。例えば:

@Entity
@Table(name = "clubs")
public class Club {
    private long id;
    private String name;
    //...

    private Collection<ClubLocation> locations;

    public Club() {
        this.name = null;
        //...

        this.locations = Collections.emptyList();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Column(nullable = false)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(mappedBy = "club")
    public Collection<ClubLocation> getLocations() {
        return locations;
    }
    public void setLocations(Collection<ClubLocation> locations) {
        this.locations = locations;
    }
}

前述したように、このエンティティを他の多くのエンティティに関連付けたいので、関係を管理するスーパークラス エンティティを定義して、Club関連付けられた各エンティティで関係を設定する必要がないようにすることをお勧めします。クラス。私はこれを使用して行います:

@Entity
@Table(name = "clubItems")
@Inheritance(strategy = InheritanceType.JOINED)
public class ClubItem {
    protected Club club;

    public ClubItem() {
        this.club = null;
    }

    @ManyToOne(optional = false)
    public Club getClub() {
        return club;
    }
    public void setClub(Club club) {
        this.club = club;
    }
}

そして、そのクラスを次のように拡張します。

@Entity
@Table(name = "clubLocations")
public class ClubLocation extends ClubItem {
    private String title;
    //...

    public ClubLocation() {
        this.title = null;
        //...
    }

    @Column(nullable = false)
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

実行しようとすると、Hibernate が次のように爆発する場合を除いて、すべて問題ないようです。

org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: ClubLocation.club in Club.locations
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:543)
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:508)
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43)
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1127)
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296)
[WARNING] [talledLocalContainer]    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1112)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1233)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:154)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:869)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:183)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:240)
[WARNING] [talledLocalContainer]    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:120)
[WARNING] [talledLocalContainer]    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
[WARNING] [talledLocalContainer]    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)

イライラすることに、クラスclub内のプロパティの getter および setter 宣言を複製すると、すべてがうまくいきます。ClubLocation具体的には、次を追加すると機能します。

@Override
@ManyToOne(optional = false)
public Club getClub() {
    return super.getClub();
}
public void setClub(Club club) {
    super.setClub(club);
}

...ClubLocationクラスに。しかし、スーパークラスに委譲するだけなので、それは無意味です。

Hibernate は、サブクラスで getter/setter を再宣言せずに継承されたマッピング フィールドを処理できるほど洗練されていないのでしょうか? Hibernate がこのケースをより適切に処理できる場合、どのようにセットアップする必要がありますか?/何が間違っているのでしょうか?

4

2 に答える 2

1

JPAに関して言えば、マッピングは完全に有効です。また、たとえばEclipseLinkではそのまま動作します。これは、Hibernate の実装の問題です。

このブログ投稿では、一種の回避策を提供しています。残念ながら、それらはすべて不完全です: テーブル構造の変更、マップされたスーパークラスでのクエリへの型の喪失など。

于 2012-07-19T06:39:36.160 に答える
1

プロジェクトに同様の設定があります。これを解決するための簡単で多かれ少なかれ良い方法は、変更することだと思います

private Collection<ClubLocation> locations;

の中へ

private Collection<ClubItem> items;

(および関連するゲッター、セッターも)。こうすれば確実にうまくいきます。

便宜上、Club で getLocations メソッドが必要な場合は、自由に作成できます。アイテムに場所のみが含まれていることが確実な場合は、コレクションをそのまま返すことができます。それ以外の場合は、Java コードでフィルター処理する必要があります。

欠点は、アイテムに場所以外の要素も含まれている場合、Java でのフィルタリングがメモリと CPU を消費するため、処理が遅くなる可能性があることです。

于 2012-07-19T06:24:11.640 に答える