JPA @OneToMany关联使用空值

时间:2018-02-23 09:24:33

标签: hibernate jpa one-to-many

我实际上是在尝试定义JPA管理的两个实体(在我的示例中称为Aggregate1和Aggregate2)之间的关系,其中映射表表示为另一个JPA实体(称为Association)

以下是Aggregate1类的定义:

@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Entity
@Table(name = "aggregate1")
public class Aggregate1 {

    @Id
    @GeneratedValue
    private Long                   id;
    @Column
    private String                 something;

    @OneToMany(fetch = FetchType.EAGER, cascade = { ALL }, orphanRemoval = true)
    @JoinColumn(name = "aggregate1_id")
    private final Set<Association> associations = new HashSet<>();

    public Aggregate1(String something) {
        this.something = something;
    }

    // methods to add, update and remove association omitted
}

和Association类的定义:

@Value
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
@AllArgsConstructor
@Entity
@Table(name = "association")
public class Association implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "aggregate1_id")
    private final Long        aggregate1Id;
    @Id
    @Column(name = "aggregate2_id")
    private final Long        aggregate2Id;
    @Column(name = "association_value")
    private final String      associationValue;

    // methods omitted
}

您可以找到运行代码here的完整示例。

我知道在两个实体之间表示多对多关系的标准方法是使用@ManyToMany关联(如此post中所述),但我不想链接直接Aggregate1Aggregate2个实体,而是通过身份链接它们。我不需要从Aggregate2Aggregate1的链接。

因此,使用此JPA映射,我确实可以使用其Aggregate1检索Association,但是当我尝试添加新关联时,在新{{1}中明确设置关联的聚合标识实体,抛出异常如下:

Association

以下是保存期间发生的Hibernate日志:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.h2.jdbc.JdbcSQLException: NULL not allowed for column "AGGREGATE1_ID"; SQL statement:
insert into association (association_value, aggregate2_id, aggregate1_id) values (?, ?, ?) [23502-196]

因此,正确设置了值,因为关联表中的初始选择显示,但似乎在保存之前2018-02-23 10:13:36.664 DEBUG 9076 --- [ main] org.hibernate.SQL : select associatio0_.aggregate2_id as aggregat1_2_0_, associatio0_.aggregate1_id as aggregat2_2_0_, associatio0_.association_value as associat3_2_0_ from association associatio0_ where associatio0_.aggregate2_id=? and associatio0_.aggregate1_id=? 2018-02-23 10:13:36.666 TRACE 9076 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [3] 2018-02-23 10:13:36.666 TRACE 9076 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1] 2018-02-23 10:13:36.686 DEBUG 9076 --- [ main] org.hibernate.SQL : insert into association (association_value, aggregate2_id, aggregate1_id) values (?, ?, ?) 2018-02-23 10:13:36.687 TRACE 9076 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [test association] 2018-02-23 10:13:36.687 TRACE 9076 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [null] 2018-02-23 10:13:36.687 TRACE 9076 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [null] 2018-02-23 10:13:36.688 WARN 9076 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 23502, SQLState: 23502 2018-02-23 10:13:36.688 ERROR 9076 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : NULL not allowed for column "AGGREGATE1_ID"; SQL statement: insert into association (association_value, aggregate2_id, aggregate1_id) values (?, ?, ?) [23502-196] aggregate1Id属性值被重置为null。

任何人都可以解释在保存期间究竟发生了什么,以及为什么这些值被重置为null?

1 个答案:

答案 0 :(得分:0)

因此DN1提出的解决方案起作用,实际上缺少以下<div class="parent"> <div class="child"></div> <div class="child a1"></div> </div>类:

AssociationId

而且,在@Value @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) @AllArgsConstructor public class AssociationId implements Serializable { private static final long serialVersionUID = 1L; private final Long aggregate1Id; private final Long aggregate2Id; } 类中,@ IdClass注释必须定义为:

Association

---编辑---

为了能够添加和删除关联,必须使用这些更改更新@Value @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) @AllArgsConstructor @Entity @Table(name = "association") @IdClass(AssociationId.class) public class Association implements Serializable { ... } 实体定义:

Aggregate1