OneToOne PrimaryKeyJoinColumn 级联
OneToOne PrimaryKeyJoinColumn Cascade
我正在努力让 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都带不上了。它抛出这个错误:
Exception Description: A non-read-only mapping must be defined for the
sequence number field.
有没有办法让这个级联起作用,这样我就不需要分别保留这两个实体了?我试图避免这种情况,因为有一些其他实体共享同一个 ID,所以就目前而言,这将是一种肮脏的工作。
谢谢
第一次尝试时,您在尝试用作外键的字段上有排序注释,没有设置 Notificator.id 字段。如果您希望它起作用,您可以创建一个从 Notificator 到 Notification 的映射,以便它的 'ID' 字段用作外键。
不幸的是,您在第二次尝试中也错误地使用了@PrimaryKeyJoinColumn 注释。 @PrimaryKeyJoinColumn用于指定映射中指定的数据库字段由@Id标记的字段控制和设置,本质上使映射insertable/updatable=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,则可以在通知器中使用 @MapsId class 而不是指定连接列,让 JPA 在托管实体中自动为您设置 Notificator.id 字段值当您的对象图被持久化时:
@Entity
class Notificator {
@Id
private UUID id;
@OneToOne
@MapsId
@JoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notification notification;
...
}
正如您所指出的,您实际上并不需要模型中的 Notificator.notification 和 Notificator.id 值,但如果您想要该值,则至少需要 Notificator.notification Notificator."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 来访问它。
我正在努力让 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都带不上了。它抛出这个错误:
Exception Description: A non-read-only mapping must be defined for the sequence number field.
有没有办法让这个级联起作用,这样我就不需要分别保留这两个实体了?我试图避免这种情况,因为有一些其他实体共享同一个 ID,所以就目前而言,这将是一种肮脏的工作。
谢谢
第一次尝试时,您在尝试用作外键的字段上有排序注释,没有设置 Notificator.id 字段。如果您希望它起作用,您可以创建一个从 Notificator 到 Notification 的映射,以便它的 'ID' 字段用作外键。
不幸的是,您在第二次尝试中也错误地使用了@PrimaryKeyJoinColumn 注释。 @PrimaryKeyJoinColumn用于指定映射中指定的数据库字段由@Id标记的字段控制和设置,本质上使映射insertable/updatable=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,则可以在通知器中使用 @MapsId class 而不是指定连接列,让 JPA 在托管实体中自动为您设置 Notificator.id 字段值当您的对象图被持久化时:
@Entity
class Notificator {
@Id
private UUID id;
@OneToOne
@MapsId
@JoinColumn(name="NOTIFICATION_ID", referencedColumnName="NOTIFICATION_ID")
private Notification notification;
...
}
正如您所指出的,您实际上并不需要模型中的 Notificator.notification 和 Notificator.id 值,但如果您想要该值,则至少需要 Notificator.notification Notificator."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 来访问它。