简体   繁体   中英

Foreign key assigned to NULL in JPA one-to-many relationship

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM