spring-data-jpa:无法用包含外键的复合主键保存实体

6ovsh4lw  于 2021-07-09  发布在  Java
关注(0)|答案(3)|浏览(462)

被难住了,完全难住了。。。
假设有两个实体,父实体和子实体,其中多个子实体对应一个父实体。父级的主键的类型为 java.util.UUID ,子级的主键是父级的uuid和序列号的组合。
问题的关键是当我试图用 childRepository.save(child) ,我得到以下异常:
原因:java.lang.illegalargumentexception:无法将类型[com.package.entities.parententity$$\u jvst149\u 0]的值转换为属性“parent”所需的类型[java.util.uuid]:propertyeditor[org.springframework.beans.propertyeditors.uuideditor]返回了类型[com.package.entitities.parententity$$\u jvst149\u 0]的不正确值
请看下面我的课。据我所知,我正在跟踪 JPA 规范正确,所以我想知道这是否是 Spring Data JPA ,可能特定于uuid类型id(类似的事情以前也发生过,请参阅datajpa-269)
我正在使用的注解 spring-boot-starter-data-jpa 1.4.1.RELEASE 父.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);
    }
}

子.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.class类

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);
    }
}

父存储库.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);
}
xnifntxz

xnifntxz1#

在我发布这个问题的几个月里,我一直没有找到合适的答案。不幸的是,我不得不通过不使用 @ManyToOne 而是通过uuid引用父级:

public class Child implements Serializable {

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

我让jpa不知道外键,如果我违反了引用完整性,就让数据库抛出一个错误。

xmjla07d

xmjla07d2#

您需要更改childkey类:

public class ChildKey implements Serializable {

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

upd:我读了jpa规范,明白它是不正确的。但对我来说是有效的。

vngu2lb8

vngu2lb83#

在多对一关系中,子实体有自己的id,父实体的id是fk而不是pk的一部分。例子

相关问题