我正在努力使Eclipselink级联持久的关系:
@Entity
class Notification {
@Id
@UuidGenerator(name="UUID_GEN")
@GeneratedValue(generator="UUID_GEN")
@Column(name = "NOTIFICATION_ID")
private UUID id;
@OneToOne(cascade = ALL, fetch = FetchType.EAGER)
@JoinFetch(JoinFetchType.INNER)
@PrimaryKeyJoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notificator notificator;
...
}
@Entity
class Notificator {
@Id
@Column(name="NOTIFICATION_ID")
private UUID id;
...
}
因此,当我试图保留Notification对象时,Eclipselink无法保留封闭的Notificator对象,因为未设置Notificator.id,因此发生了约束失败。
在第二次尝试中,我尝试使用@MapId注释:
@Entity
class Notification {
@Id
@UuidGenerator(name="UUID_GEN")
@GeneratedValue(generator="UUID_GEN")
@Column(name = "NOTIFICATION_ID")
private UUID id;
@OneToOne
@MapsId
private Notificator notificator;
...
}
@Entity
class Notificator {
@Id
@Column(name="NOTIFICATION_ID")
private UUID id;
@OneToOne
PrimaryKeyJoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notification notification; // didn't need to have it here, but fine.
...
}
这样,我甚至无法携带EntityManager。它抛出了这个错误:
异常说明:必须为。定义非只读映射 序号字段。
有没有办法让这个级联工作,所以我不需要分别保留这两个实体?我试图避免这种情况,因为有一些其他实体共享这个相同的ID,所以它将是一种肮脏的工作。
谢谢
答案 0 :(得分:1)
首次尝试时,您在尝试用作外键的字段上有序列注释,没有任何设置Notificator.id字段。如果您希望这一点起作用,您可以创建一个从Notificator到Notification的映射,以便它的ID为#&字段用作外键。
不幸的是,您在第二次尝试时也错误地使用了@PrimaryKeyJoinColumn注释。 @PrimaryKeyJoinColumn用于指定映射中指定的数据库字段由标记为@Id的字段控制和设置,实质上使映射可插入/可更新= false。
为了匹配你想要的结构,你应该尝试:
@Entity
class Notification {
@Id
@UuidGenerator(name="UUID_GEN")
@GeneratedValue(generator="UUID_GEN")
@Column(name = "NOTIFICATION_ID")
private UUID id;
@OneToOne(mappedby="notification", cascade = ALL, fetch = FetchType.EAGER)
@JoinFetch(JoinFetchType.INNER)
private Notificator notificator;
...
}
@Entity
class Notificator {
@Id
@Column(name="NOTIFICATION_ID")
private UUID id;
@OneToOne
@JoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID", insertable=false, updatable=false)
private Notification notification;
...
}
这并不完全符合您的要求,因为上面的示例要求您在引用的Notification.id中的值可用后自己设置Notificator.id值(post persist / flush)。
如果您使用的是JPA 2.0,则可以使用Notificator类中的@MapsId而不是指定连接列,以便在持久保存对象图时让JPA在托管实体中自动设置Notificator.id字段值: / p>
@Entity
class Notificator {
@Id
private UUID id;
@OneToOne
@MapsId
@JoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notification notification;
...
}
正如您所指出的,您并不需要模型中的Notificator.notification和Notificator.id值,但如果您想要Notificator的值,则至少需要Notificator.notification。&#34 ; NOTIFICATION_ID"字段来自通知。 JPA 2.0允许您删除Notificator.id并使用Notificator.notification关系作为实体ID使用:
@Entity
class Notificator {
@Id
@OneToOne
@JoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notification notification;
...
}
这允许您仍然使用UUID值进行身份查找。 FetchJoins等可以确保始终提取关系,但是缺点是希望使用ID值的JPQL需要使用notificator.notification.id来访问它。