JPA 一对多关系中分配给 NULL 的外键
Foreign key assigned to NULL in JPA one-to-many relationship
我有以下一对实体类:
@Entity(name="metadata")
public class Metadata {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// Note: Hibernate CascadeType.ALL is also being used elsewhere in this class, hence
// the fully qualified class name used below
@OneToMany(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "metadata")
private List<Attachment> attachments;
// getters and setters
}
@Entity(name="attachment")
public class Attachment {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "metadata_id", referencedColumnName = "id", nullable = false, updatable = false)
private Metadata metadata;
// getters and setters
}
为了完整起见,下面是我构建 Metadata
对象的方式:
Metadata metadata = modelMapper.map(req, Metadata.class);
List<Attachment> attachments = new ArrayList<>();
// the files come as a parameter to a Spring controller endpoint (FYI)
for (MultipartFile file : files) {
Attachment attachment = new Attachment();
attachment.setContents(file.getBytes());
attachment.setFilename(file.getOriginalFilename());
attachments.add(attachment);
}
metadata.setAttachments(attachments);
metadata.setDraft(isDraft);
myJPARepository.save(metadata);
我在创建 Metadata
实体然后从我的 JPA 存储库调用 save()
时观察到的是所有数据都正确写入了我的数据库 (Postgres)。但是,连接列 metadata_id
始终是 NULL
。起初,我认为这可能是由于未设置 referencedColumnName
属性(默认为 ""
)引起的。但是,如上所示添加它确实解决了问题。
有谁知道为什么连接列 metadata_id
在数据库 table 中总是显示为 NULL
?
您需要同步您的两个对象,截至目前您正在创建元数据对象并向其添加附件并且您有级联以便将两个实体保存到它们各自的 table.
但是,因为你有双向关系,你只是在这里同步关系的一侧,你需要为每个附件对象设置相同的元数据对象,然后休眠将能够link外键。
我建议在元数据对象上使用添加函数,而不是 setter,就像这样
public void addAttachment(Attachment attachment) {
attachments.add(attachment);
attachment.setMetadata(this);
}
这样两个对象都会同步,在你的 for 循环中使用它,你可能必须在这样做之前在元数据对象中初始化你的集合,或者你可以先签入上面的 add
函数如果 attachments
列表为空则创建一个然后添加。
我有以下一对实体类:
@Entity(name="metadata")
public class Metadata {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// Note: Hibernate CascadeType.ALL is also being used elsewhere in this class, hence
// the fully qualified class name used below
@OneToMany(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "metadata")
private List<Attachment> attachments;
// getters and setters
}
@Entity(name="attachment")
public class Attachment {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "metadata_id", referencedColumnName = "id", nullable = false, updatable = false)
private Metadata metadata;
// getters and setters
}
为了完整起见,下面是我构建 Metadata
对象的方式:
Metadata metadata = modelMapper.map(req, Metadata.class);
List<Attachment> attachments = new ArrayList<>();
// the files come as a parameter to a Spring controller endpoint (FYI)
for (MultipartFile file : files) {
Attachment attachment = new Attachment();
attachment.setContents(file.getBytes());
attachment.setFilename(file.getOriginalFilename());
attachments.add(attachment);
}
metadata.setAttachments(attachments);
metadata.setDraft(isDraft);
myJPARepository.save(metadata);
我在创建 Metadata
实体然后从我的 JPA 存储库调用 save()
时观察到的是所有数据都正确写入了我的数据库 (Postgres)。但是,连接列 metadata_id
始终是 NULL
。起初,我认为这可能是由于未设置 referencedColumnName
属性(默认为 ""
)引起的。但是,如上所示添加它确实解决了问题。
有谁知道为什么连接列 metadata_id
在数据库 table 中总是显示为 NULL
?
您需要同步您的两个对象,截至目前您正在创建元数据对象并向其添加附件并且您有级联以便将两个实体保存到它们各自的 table.
但是,因为你有双向关系,你只是在这里同步关系的一侧,你需要为每个附件对象设置相同的元数据对象,然后休眠将能够link外键。
我建议在元数据对象上使用添加函数,而不是 setter,就像这样
public void addAttachment(Attachment attachment) {
attachments.add(attachment);
attachment.setMetadata(this);
}
这样两个对象都会同步,在你的 for 循环中使用它,你可能必须在这样做之前在元数据对象中初始化你的集合,或者你可以先签入上面的 add
函数如果 attachments
列表为空则创建一个然后添加。