Davide
Davide

Reputation: 95

bidirectional onetomany on spring boot and hibernate, best way to save

I have 2 entities:

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Table(name = "source_company")
public class SourceCompany {
    @Id
    @EqualsAndHashCode.Include
    private UUID id;

    private String name;

    @OneToMany( mappedBy = "company")
    private final Set<SourceUser> users = new HashSet<>();

    @Column(name = "version")
    @Version
    private Long version;
}

@Data
@Entity
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Table(name = "source_user")
public class SourceUser {
    @Id
    @EqualsAndHashCode.Include
    private UUID id;

    private String name;

    @Column(name = "version")
    @Version
    private Long version;

    //ref
    @ManyToOne
    @JoinColumn(name = "fk_source_company")
    private SourceCompany company;
}

Is it correct to save in this way (only 2 save)?

        @Test
    public void testSourceUserSave() {
        SourceCompany sourceCompany= new SourceCompany();
        sourceCompany.setName("xxx");
        sourceCompany.setId(UUID.fromString("2bf05cbc-d530-11eb-b8bc-0242ac130003"));

        SourceUser sourceUser= new SourceUser();
        sourceUser.setName("dev-team");
        sourceUser.setId(UUID.fromString("4bede7a0-d530-11eb-b8bc-0242ac130003"));

        sourceUser.setCompany(sourceCompany);
        sourceCompany.getUsers().add(sourceUser);

        sourceCompanyRepository.save(sourceCompany);
        sourceUserRepository.save(sourceUser);

        assertNotNull(sourceUser);
        assertEquals(sourceUser.getCompany().getId(), sourceCompany.getId());
        assertEquals(sourceCompany.getUsers().stream().findFirst().get().getId(), sourceUser.getId());

    }

or I need to save the user (without company) and the company (without user) and after that to update the user with a save and the company (without save because is not the owner) like this (3 save):

        @Test
    public void testSourceUserSave() {
        SourceCompany sourceCompany= new SourceCompany();
        sourceCompany.setName("xxx");
        sourceCompany.setId(UUID.fromString("2bf05cbc-d530-11eb-b8bc-0242ac130003"));

        SourceUser sourceUser= new SourceUser();
        sourceUser.setName("dev-team");
        sourceUser.setId(UUID.fromString("4bede7a0-d530-11eb-b8bc-0242ac130003"));

        sourceUserRepository.save(sourceUser);
        sourceCompanyRepository.save(sourceCompany);

        sourceUser.setCompany(sourceCompany);
        sourceCompany.getUsers().add(sourceUser);

        sourceUserRepository.save(sourceUser);

        assertNotNull(sourceUser);
        assertEquals(sourceUser.getCompany().getId(), sourceCompany.getId());
        assertEquals(sourceCompany.getUsers().stream().findFirst().get().getId(), sourceUser.getId());

    }

It seems, looking in the db, that the first way works, so in future can I update only the owner side (I mean update and save) and so can I update the not-owner side only in the object without save it again?

Thanks in advance

Upvotes: 0

Views: 571

Answers (1)

L_Cleo
L_Cleo

Reputation: 1527

You usually tend to save only one of the objects. This can be done adding the

@ManyToOne(cascade = CascadeType.PERSIST)

to the mapping annotation. This makes sure that the nested entities get persisted too You would need to do just:

SourceCompany sourceCompany= new SourceCompany();
sourceCompany.setName("xxx");
sourceCompany.setId(UUID.fromString("2bf05cbc-d530-11eb-b8bc-0242ac130003"));

SourceUser sourceUser= new SourceUser();
sourceUser.setName("dev-team");
sourceUser.setId(UUID.fromString("4bede7a0-d530-11eb-b8bc-0242ac130003"));

sourceUser.setCompany(sourceCompany);

sourceUserRepository.save(sourceUser);

One more thing to note is that the .save method actually returns an entity itself. That entity is the persisted entity just created. Basically if you manage everything within a single transactional method any modification to the persisted entity within that method (transaction) will be applied without calling any save, merge or update method I suggest reading about the @Transactional annotation

Upvotes: 1

Related Questions