最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - Is it necessary to verify if the related @ManyToOne entity exists before saving the parent entity in JPA - Stack Overflow

programmeradmin7浏览0评论

For example, when an entity Person which has a @ManyToOne relationship to Company (not cascade) is received for saving, should I manually call companyService.findById() to check that it exists before saving the Person entity?

It is just a matter of protection because if I do not check it and the company does not exists, the person entity will not be persisted (at least in my tests)

What's the best practice for this? I would like to avoid always fetching before saving, and even more if it is a bulk create of persons where the Person entity contains multiple Many to One relationships.

I leave you a simple piece of code.

@Data
@Entity
@Table(name = "person")
public class PersonEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID uuid;

    private String name;

    @ManyToOne
    @JoinColumn(name = "company_id")
    private CompanyEntity company;

    @ManyToOne
    @JoinColumn(name = "other_entity_id")
    private OtherEntity otherEntity;

}

For example, when an entity Person which has a @ManyToOne relationship to Company (not cascade) is received for saving, should I manually call companyService.findById() to check that it exists before saving the Person entity?

It is just a matter of protection because if I do not check it and the company does not exists, the person entity will not be persisted (at least in my tests)

What's the best practice for this? I would like to avoid always fetching before saving, and even more if it is a bulk create of persons where the Person entity contains multiple Many to One relationships.

I leave you a simple piece of code.

@Data
@Entity
@Table(name = "person")
public class PersonEntity{

    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID uuid;

    private String name;

    @ManyToOne
    @JoinColumn(name = "company_id")
    private CompanyEntity company;

    @ManyToOne
    @JoinColumn(name = "other_entity_id")
    private OtherEntity otherEntity;

}
Share Improve this question edited Mar 22 at 14:09 Vishal 1,4163 gold badges14 silver badges30 bronze badges asked Mar 22 at 1:37 EvoldevEvoldev 356 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

When you dealing with the tag @ManyToOne you can rely on the "database" constrain, the id of the entity.

If you concerned on the Bulk operation, there is Optimization you can do. You can optimize by fetching all referenced entities in a single query before performing the bulk save. This reduces the number of database queries (related to the reference entity).

public void savePersons(List<PersonEntity> persons) {
    // getting all the company id
    Set<UUID> companyIds = persons.stream()
        .map(PersonEntity::getCompany)
        .filter(Objects::nonNull)
        .map(CompanyEntity::getId)
        .collect(Collectors.toSet());
    
    // find to db the reference of company that 
    // will be used in Person entity. And build as map (for efficient check exists by id)
    Map<UUID, CompanyEntity> companies = companyService.findAllById(companyIds).stream()
        .collect(Collectors.toMap(CompanyEntity::getId, Function.identity()));

    for (PersonEntity person : persons) {
        if (
            person.getCompany() != null && 
            // check the company reference id is find in Map(from db)
            !companies.containsKey(person.getCompany().getId())
        ) {
            // you can either skip/remove the person or throw error like this
            throw new EntityNotFoundException("Company not found for person: " + person.getName());
        }
    }

    personRepository.saveAll(persons);
}

Pros: More efficient than checking each entity individually in bulk operations. Cons: Requires more complex logic to handle the fetching and mapping of referenced entities.

It depends. Since this is an opinion-based question, here are my two cents.

If a "company" doesn't exist and there's nothing to do about it - no eligibility checks, no need to verify associations - I'd leave it as is. This is often the case for entities like addresses. There will only be an issue if there's a bug that sends an incorrect ID. If not, it's likely someone tampering with the request, and we don’t need to entertain them with a proper validation message. I assume this applies to your case since you can opt out of fetching the entity (JpaRepository#getReferenceById).

If validation is necessary, like for eligibility checks, logging, or ensuring associations are intact, I'd implement some sort of caching mechanism.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论