@Transactional in bidirectional relation with Spring Data returns null

P.Juchimowicz :

I am using Spring Data and @Transactional annotation(for automatic rollback after tests). I have simple bidirectional relation between account and user(owning side):

@Entity
@Table(name = "ACCOUNT_T")
public class AccountEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String email;
    private String password;
    private String verificationCode;
    private Boolean active = false;

    @OneToOne(mappedBy = "account", fetch = FetchType.EAGER, 
              cascade = {CascadeType.MERGE, CascadeType.PERSIST,
                         CascadeType.DETACH, CascadeType.REFRESH})
    private UserEntity user;
}

@Entity
@Table(name = "USER_T")
public class UserEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String surname;
    private String phone;
    private LocalDate birthDate;

    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
    @JoinColumn(name = "account_id")
    private AccountEntity account;
}

I am using JpaRepositories and fetching is set to eager. Why sometimes when I get objects from database I can't get their child objects-null is returned. It depends on from which side I add objects. I have written simple test using Junit5:

@ExtendWith(SpringExtension.class)
@SpringBootTest
@Transactional
class UserAndAccountRepositoriesTest {

    void testA() {
        UserEntity userEntity = new UserEntity();
        setUserProperties(userEntity);
        AccountEntity accountEntity = new AccountEntity();
        setAccountProperties(accountEntity); //just setting values for fields
        accountEntity.setUser(userEntity);
        accountRepository.save(accountEntity);

        accountRepository.findAll().get(0).getUser(); //returns user
        userRepository.findAll().get(0).getAccount(); //returns null,but should return account related to that user
    }

    void testB() {
        UserEntity userEntity = new UserEntity();
        setUserProperties(userEntity);
        AccountEntity accountEntity = new AccountEntity();
        setAccountProperties(accountEntity);
        accountEntity.setUser(userEntity);
        accountRepository.save(accountEntity);

        accountRepository.findAll().get(0).getUser(); //again returns null,but shouldn't
        userRepository.findAll().get(0).getAccount(); //returns account
    }
}

Without @Transactional everything works fine - I am not getting null. What am I doing wrong?

buræquete :

You'd need to set both sides of a relationship for explicitly defining it. Try adding userEntity.setAccount(accountEntity) during your setup case, this would resolve the issue.

Hibernate won't help you and assume just because you set a -> b, it would set b <- a for you within the other entity.

The reason why it might work without @Transactional is that, without the annotation you are committing your setup data into whatever datasource you are using, and nothing is rollbacked at the end, and since you are selecting data without any id with findAll, you are getting previous user/account entites that have already been committed, some with relationship & some without, thus the random error you are getting.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=78360&siteId=1