I have the following pair of entity classes:
@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
}
For completeness, here is how I am building the Metadata
object:
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);
What I observe when creating a Metadata
entity and then calling save()
from my JPA repository is that all data does get correctly written to my database (Postgres). However, the join column metadata_id
is always NULL
. At first, I thought this might have been caused due to the referencedColumnName
attribute not being set (whose default is ""
). However, adding this in as you see above did remedy the problem.
Does anyone know why the join column metadata_id
is always appearing as NULL
in the database table?
You need to synch both of your object, as of now you are creating metadata object and adding attachment to it and you have cascade so that will save both entities into their respective table.
But, since you have bidirectional relationship, you are only synching one side of relation ship here only, you need to set the same metadata object to each attachment object as well, then hibernate will be able to link the foreign key.
Instead of setter I would suggest use a add function on metadata object something like this
public void addAttachment(Attachment attachment) {
attachments.add(attachment);
attachment.setMetadata(this);
}
This way both the object would be in synch, use that inside in your for loop, you may have to initialise your collection inside metadata object before doing that or you can first check in above add
function that if attachments
list is null then create one and then add.