与 Spring Data 双向关系的 @Transactional 返回 null

P.J*_*icz 6 java hibernate spring-transactions spring-data-jpa

我正在使用 Spring Data 和 @Transactional 注释(用于测试后自动回滚)。我在帐户和用户(拥有方)之间有简单的双向关系:

@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;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用 JpaRepositories 并将获取设置为 eager。为什么有时当我从数据库获取对象时,我无法获取它们的子对象 - 返回 null。这取决于我从哪一侧添加对象。我使用 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
    }
}
Run Code Online (Sandbox Code Playgroud)

如果没有@Transactional一切正常 - 我不会变得空。我究竟做错了什么?

bur*_*ete 3

您需要设置关系的双方才能显式定义它。尝试userEntity.setAccount(accountEntity)在设置过程中添加,这可以解决问题。

Hibernate 不会帮助您,并假设仅仅因为您设置了a -> b,它就会b <- a在其他实体中为您设置。

它可能在没有注释的情况下工作的原因@Transactional是,如果没有注释,您将把设置数据提交到您正在使用的任何数据源中,并且最后不会回滚任何内容,并且由于您选择的数据没有任何idwith findAll,因此您将获得以前的用户/已提交的帐户实体,有些有关系,有些没有关系,因此您会得到随机错误。