1

我将 Hibernate 与 JPA 一起使用,并且有这样的关系:

@Entity
@Table(name = "first")
public class First {
...
@OneToMany(mappedBy = "first")
private List<Availability> availabilities;
...
}


@Entity
@Table(name = "second")
public class Second {
...
@OneToMany(mappedBy = "second")
private List<Availability> availabilities;
...
}

@Entity
@Table(name="availability")
public class Availability implements Serializable {
@Id
@ManyToOne
@JoinColumn(name = "first_id")
private First first;

@Id
@ManyToOne
@JoinColumn(name = "second_id")
private Second second;

@Column(name = "availability")
private Integer availability;

...
hashcode and equals
}

我想分别管理这 3 个实体。第一个和第二个工作正常,但是当我尝试 merge() 第三个时,postgresql 得到一个空值而不是 id,并且抛出了约束违规异常。为什么?我什至可以在这个实体上使用合并来向表中添加新行吗?

更新:合并是这样的:

public Availability setAvailability(Availability a) {
return em.merge(a);
}

可用性从前端反序列化(仅提一下,“关键”类的集合在其中分离)。

4

2 回答 2

2

您已经解决了您的问题,但我在这里为需要使用多列主键且无法更改数据库的用户留下一个建议。

显然,在尝试合并时,单独使用多个 @Id 注释会产生不一致:您分配所有字段,然后在合并期间用 @Id 注释的字段分配空值(合并失败)。我可以猜到一个解释:hibernate 不希望有一个分配了@Ids 的非托管对象;但这只是多列主键的问题,所以这似乎是一个错误。

注意:调用persist而不是merge 有效(但在某些情况下,您会重复行或出现数据库约束错误,因为这种情况下的主键仅在数据库级别检查)。

我使用@IdClass 解决了类似的问题。在您的旧代码中,您必须:

  1. 创建一个类(例如AvailabilityId),其中包含firstsecond字段(完全匹配类 Availability 中用 @Id 注释的字段),并覆盖equalshashCode方法
  2. 除了@Override 之外,AvailabilityId 中不需要任何注释(顺便说一下,如果您在Availability 和AvailabilityId 字段上都使用@Column,您可能会遇到可怕的错误)。这不必是实体或表,它是 POJO。
  3. 使用 @IdClass(AvailabilityId.class) 注释类可用性

应该是这样的。抱歉迟到了 3 年,但是如果您摆脱了多列主键,那么无论如何您现在处于一个更好的世界。

我尝试了@EmbeddedId,但它打破了其他一些要求(简单的 json-> 对象转换和查询在 SQL 和 HQL 中都可以进行微调)。

于 2017-10-18T14:21:32.460 回答
0

我通过避免使用复合 ID 解决了这个问题。在重新考虑问题后,我发现这种情况下我实际上可以使用唯一约束。

@Entity
@Table(name = "availabilities", uniqueConstraints = { @UniqueConstraint(columnNames = {
    "first_id", "second_id" }) })
@SequenceGenerator(initialValue = 1, name = "availabilities_sequence", sequenceName =     "availabilities_sequence")
public class Availability implements IAvailability, Serializable {

private static final long serialVersionUID = -2977047920673617888L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "availabilities_sequence")
@Column(name = "id")
private Integer id;

@ManyToOne
@JoinColumn(name = "first_id", nullable=false)
private First first;

@ManyToOne
@JoinColumn(name = "second_id", nullable=false)
private Second second;

@Column(name = "availability", nullable=false)
private Integer availability;

...
}
于 2014-05-28T07:39:35.350 回答