2017-01-04 3 views
0

困惑を、含まれている複合主キーを持つエンティティを保存できません...春データJPAは:全く困惑外部キー

は1人の親に多くの子エンティティと、2つのエンティティ、親と子を想定します。親の主キーのタイプはjava.util.UUIDで、子の主キーは親のUUIDとシーケンス番号の複合です。私はchildRepository.save(child)を使用して新しい子を保存しようとすると、

問題の短いです、私は次の例外を取得:

によって引き起こさ

:java.lang.IllegalArgumentExceptionが: 型の値を変換できません[COM .package.entities.ParentEntity $$ _ jvst149_0]必要なタイプに [java.util.UUID]プロパティの '親':PropertyEditorは は[org.springframework.beans.propertyeditors.UUIDEditor] COM [タイプ の不適切な値が返されます。 package.entities.ParentEntity _ $$ _ jvst149_0]

下記のクラスをご覧ください。私が使用しています

(同じようなことが前に起こった、 DATAJPA-269を参照してください)私は正しく JPAスペックを以下していますので、これは Spring Data JPAのバグであるならば、私は、UUID種別IDに、おそらく特定思ったんだけど言うことができる最善の注意 spring-boot-starter-data-jpa 1.4.1.RELEASE

Parent.java:

@Entity 
@Table(name = "parent") 
public class Parent implements Serializable { 

    @Id 
    @GeneratedValue(generator = "uuid") 
    @GenericGenerator(name = "uuid", strategy = "uuid2") 
    private UUID id; 

    //...other fields, getters + setters... 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     Parent that = (Parent) o; 
     return Objects.equals(id, that.id); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(id); 
    } 
} 

Child.java

@Entity 
@Table(name = "child") 
@IdClass(ChildKey.class) 
public class Child implements Serializable { 

    @Id 
    @ManyToOne 
    @JoinColumn(name = "parent_id", referencedColumnName = "id", insertable = false, updatable = false) 
    private Parent parent; 
    @Id 
    private Integer seqNum; 

    //...other fields, getters + setters... 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     Child that = (Child) o; 
     return Objects.equals(parent, that.parent) && 
       Objects.equals(seqNum, that.seqNum); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(parent, seqNum); 
    } 
} 

ChildKey

public class ChildKey implements Serializable { 

    private UUID parent; 
    private Integer seqNum; 

    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     ChildKey that = (ChildKey) o; 
     return Objects.equals(parent, that.parent) && 
       Objects.equals(seqNum, that.seqNum); 
    } 

    @Override 
    public int hashCode() { 
     return Objects.hash(parent, seqNum); 
    } 
} 

の.class ParentRepository.java

@Repository 
public interface ParentRepository extends JpaRepository<Parent, UUID> { 
} 

ChildRepository.java

@Repository 
public interface ChildRepository extends CrudRepository<Child, ChildKey> { 
} 

そして、私は実行最後に、コード:多対一で

@Transactional 
public void createChild(Parent parent) { 
    // needed to do this to get over "detached entity passed to persist" 
    parent = parentRepository.getOne(parent.getId()); 
    child = new Child(); 
    child.setParent(parent); 
    child.setSeqNum(1); 
    childRepository.save(child); 
} 

答えて

0

あなたの子エンティティが持っている関係自身のID、および親エンティティからのIDは、PKの一部ではないFKです。

+0

ありがとう - 私は答えを感謝しますが、私は私が続くとは思わない。私が使ったすべてのRDBMSでは、子供のプライマリ・キーが外部キーで構成されていることに問題はありませんでした。実際、これはデータベースを正規化するための共通の方法です。 – Jpnh

0

私はこの質問を投稿してから数ヶ月、私は適切な答えを見つけられませんでした。私は残念ながら@ManyToOneを使用しないことで問題を回避し、代わりにちょうどUUIDによって親を参照する必要がありました:

public class Child implements Serializable { 

    @Id 
    private UUID parentId; 
    @Id 
    private Integer seqNum; 

私は、外部キーの無知JPAを残して、ちょうど私が参照整合性に違反する必要があり、データベースがエラーをスローしてみましょう。

0

あなたのChildKeyクラスを変更する必要があります:

public class ChildKey implements Serializable { 

    private Parent parent; // <-- Parent type instead of UUID 
    private Integer seqNum; 
    ... 

はUPD:私はJPAの仕様をお読みください。それが間違っていることを理解しました。しかし、それは私の場合に働く。

+0

興味深い!ありがとう。私はもはやこの質問に影響を与えたコードベースで作業しませんが、次回はこれを試してみます。私は試してみます。 – Jpnh

関連する問題