6

Car と Engine という 2 つのエンティティがあります (例の名前ですが、ロジックは同じです)。

@Entity
public class Car {
    @Id
    private Long id;

    @OneToOne(mappedBy = "car", cascade = Cascade.ALL)
    private Engine engine;
    ...


}

@Entity
public class Engine {
    @Id
    private Long id; // 1

    @MapsId // 2
    @OneToOne
    @JoinColumn(name = "car_id") // join column is optional here
    private Car car;
    ...
} 

だから、私はする:

em.save(car); // successfully saved, data is in the database, but (see below)
TypedQuery<Engine> query = em.createQuery("select engine from Engine engine where engine.car = :car", Engine.class)
query.setParameter("car", car);

query.getResultList();

例外をスローします:

ERROR [main] (JDBCExceptionReporter.java:234) - No value specified for parameter 1.
 WARN [main] (TestContextManager.java:409) - Caught exception while allowing TestExecutionListener     [org.springframework.test.context.transaction.TransactionalTestExecutionListener@17e5cbd] to process 'after' execution for test: method , exception [org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.DataException: could not execute query; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.DataException: could not execute query]

ただし、Engine エンティティを車のインスタンス自体に @Id のみを持つように変更すると (//1 を削除し、// 2 を @Id に変更)、機能します。

JPAのドキュメントによると、同じように動作するはずです(少なくとも私は予想していました)。

私の環境: PostgreSQL 9、Spring Framework 3.1、Hibernate 3.6.8.Final、Tomcat 7 (JPA サポートは Spring インストルメンテーションによって追加されます)。

更新:EclipseLinkで両方のマッピングを試しましたが、うまくいきました。したがって、問題はおそらく Hibernate のどこかにあります。Hibernateで強制的に動作させる方法はまだわかりません。

4

1 に答える 1

6

それに基づいて、エンジンクラスで複合キーを使用しているIDを想定しています。@MapsId は、次の例のように @EmbeddedId がある場合にのみ使用されます。

依存エンティティが埋め込み ID を使用して主キーを表す場合、関係属性に対応する埋め込み ID の属性は、親エンティティの主キーと同じタイプである必要があり、MapsId アノテーションに適用される属性によって指定される必要があります。関係属性。

@Embeddable
public class DependentId {
  String name;
  long empPK; // corresponds to PK type of Employee
}
@Entity
public class Dependent {
  @EmbeddedId DependentId id;
...
// id attribute mapped by join column default
  @MapsId("empPK") // maps empPK attribute of embedded id
  @ManyToOne Employee emp;
}

あなたのコード例に従って。

 @Embeddable
    public class NewKey{
      private Long id;
      private Long carId; // corresponds to PK type of Employee
    }

@Entity
public class Car {
    @Id
    private Long id;

    @OneToOne(mappedBy = "car", cascade = Cascade.ALL)
    private Engine engine;
}

@Entity
public class Engine {
    @EmbeddedId NewKey id;

    @MapsId("carId") // 2
    @OneToOne
    @JoinColumn(name = "car_id") // join column is optional here
    private Car car;
    ...
} 

リレーションシップの親キーを新しいキーとして使用しようとしたと仮定します

依存エンティティが単一の主キー属性 (つまり、関係属性または関係属性に対応する属性) を持ち、親エンティティの主キーが単純な主キーである場合、依存エンティティの主キーは単純です。親エンティティと同じタイプの主キー (および EmbeddedId も IdClass も指定されていません)。この場合、(1) 関係属性に Id アノテーションが付けられているか、(2) 別の Id 属性が指定され、関係属性に MapsId アノテーションが付けられています (そして、MapsId アノテーションの値要素は指定されていません)。

その場合、休止状態 4.3 を使用してテストされた、以下に示すように構成が機能するはずです。

ここに画像の説明を入力

于 2014-04-19T07:34:22.610 に答える