1

次のような 2 つの JPA エンティティがあります。

@Entity
class Customer {
   @Id
   @GeneratedValue
   Long id

   @OneToOne(cascade = CascadeType.ALL)
   @PrimaryKeyJoinColumn
   CustomerInformation customerInformation
}


@Entity
class CustomerInformation {
   @Id
   @OneToOne
   @JoinColumn(name = "id")
   Customer customer

   String firstName
   String lastName
}

spring-data-jpa を使用して DAO レイヤーを生成しています。これはあまり興味深いものではありませんが、次のとおりです。

public interface CustomerRepository extends CrudRepository<Customer, Long> {
}

これを春のコンテキストで呼び出し、 @Transactional アノテーションを使用して、いつトランザクションをデータベースにコミットするかを JPA プロバイダーに伝えます。テストのために、@PersistenceContext を使用してエンティティ マネージャーを取得し、手動でフラッシュしてトランザクションを終了します。アプリケーションの性質上、customerInformation オブジェクトが関連付けられていない Customer がデータベースに存在する場合があります。同じトランザクションで新しい顧客と customerInformation オブジェクトを作成すると、期待どおりに機能します。たとえば、これは機能します:

@Transactional
public void createNewCustomer() {
   Customer cust = new Customer();
   CustomerInformation custInf = new CustomerInformation;
   custInf.setCustomer(cust);
   custInf.setFirstName("asdf");
   custInf.setLastName("hjkl");

   cust.setCustomerInformation(custInf);

   customerRepository.save(cust);
}

しかし、既存の顧客を更新したい場合、null ID を持つ CustomerInformation オブジェクトを挿入しようとする問題に遭遇します。たとえば、これは惨めに失敗します。

@Transactional
public void updateExistingCustomer(Long userId) {

   Customer foundCustomer = customerRepository.findOne(userId);

   if (foundCustomer.getCustomerInformation() == null) {
      CustomerInformation custInf = new CustomerInformation();
      custInf.setCustomer(foundCustomer);
      custInf.setFirstName("asdf");
      custInf.setLastName("hjkl");

      cust.setCustomerInformation(custInf);

      customerRepository.save(foundCustomer);
   }
}

これは次のエラー メッセージで失敗します。

Hibernate: insert into CustomerInformation (firstName, lastName, id) values (?, ?, ?)
Feb 1, 2013 7:40:12 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 20000, SQLState: 23502
Feb 1, 2013 7:40:12 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Column 'ID'  cannot accept a NULL value.

私は何か誤解していますか?どんな助けでも大歓迎です。

前もって感謝します!

4

2 に答える 2

1

Idfield もgenerated valueとしてマークする必要があるため、hibernate はそれに値を設定します。

@Entity
class Customer {
   @Id
   @GeneratedValue // !!!
   Long id

...

@Entity
class CustomerInformation {
   @Id
   @GeneratedValue // !!!
   @OneToOne
   @JoinColumn(name = "id")
   Customer customer

...
于 2013-02-02T01:12:22.230 に答える
0

エンティティを次のように変更しました。

@Entity
class CustomerInformation {

    @Id
    Long id

    @MapsId
    @OneToOne
    @JoinColumn(name = "id")
    Customer customer

    String firstName
    String lastName
}

そして、すべてがうまくいきました。私が知る限りCustomerInformation、2 番目のバージョンが実際の ID をモデル化することを除いて、両方のバージョンで同じ SQL が生成されますが、これは必ずしも必要ではありません。これを別の質問で展開しますが、上記のコードで問題が解決しました。

于 2013-02-05T23:03:15.413 に答える