2

これらのテーブルがあるとしましょう:

テーブル A には、次の 2 つのフィールドに複合主キーがあります。

  • 従業員 ID (文字列)
  • トランザクション ID (ロング)

テーブル B にも複合主キーがありますが、3 つのフィールドがあります。

  • 従業員 ID (文字列)
  • トランザクション ID (ロング)
  • 日付(日付)

テーブル B には、「FK1」と呼ばれる従業員 ID とトランザクション ID の外部キーがあります (簡単にするため)。

テーブル A で使用される複合 ID は、マップされたいくつかの Hibernate クラスで使用されるため、再利用できるクラスを作成します。

@Embeddable
public class EmployeeTransactionComposite {

    private String employeeId;
    private Long transactionId;

}

したがって、テーブル A にマップされたクラスは次のようになります。

public ClassA implements Serializable {

    private EmployeeTransactionComposite id;
    // rest of fields

    @EmbeddedId
    public EmployeeTransactionComposite getId() {
        return id;
    }
}

テーブル B にマップされたクラスは次のようになります。

public ClassB implements Serializable {

    private ClassBCompositeId id;
    // fields

    @EmbeddedId
    public getId() {
        return this.id;
    }

    @Embeddable
    public class ClassBCompositeId implements Serializable {

        private EmployeeTransactionComposite composite;
        private Date date;

        @ManyToOne
    @ForeignKey(name="FK1")
        public EmployeeTransactionComposite getComposite() {
            return composite;
        }

        @Column(name="THEDATE")
        public Date getDate() {
            return date;
        }
    }
}

明らかに、それが機能している場合、私はこれを投稿しません。次のようなスタックトレースで爆発します。

Caused By: java.lang.NullPointerException
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1419)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1359)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1728)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1779)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:189)
Truncated. see log file for complete stacktrace

これは従来のスキーマへのマッピングであるため、変更はできません。誰でも助けることができますか?

4

1 に答える 1

2

ManyToOne は主キー クラスを指すことはありませんが、常にエンティティを指します。したがって、このマッピングは正しくありません。

@ManyToOne
@ForeignKey(name="FK1")
public EmployeeTransactionComposite getComposite() {
    return composite;
}

主キー クラスで関連付けを定義せず、基本的な列 (または基本的な列を含む埋め込み可能オブジェクト) のみを定義することをお勧めします。次に、エンティティ自体で関連付けを定義し、この関連付けで @MapsId アノテーションを使用して、この関連付けが ID のマッピングに使用される列と同じ列を使用することを Hibernate に伝えます。

ドキュメントには、まさにあなたがやろうとしていることを行うマッピングの例が含まれています:

埋め込まれた ID 自体に、関連付けられたエンティティの主キーを含めることができます。

@Entity
class Customer {
   @EmbeddedId CustomerId id;
   boolean preferredCustomer;

   @MapsId("userId")
   @JoinColumns({
      @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
      @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
   })
   @OneToOne User user;
}

@Embeddable
class CustomerId implements Serializable {
   UserId userId;
   String customerNumber;

   //implements equals and hashCode
}

@Entity 
class User {
   @EmbeddedId UserId id;
   Integer age;
}

@Embeddable
class UserId implements Serializable {
   String firstName;
   String lastName;

   //implements equals and hashCode
}
于 2012-05-18T12:16:25.200 に答える