与Spring Data双向关联的@Transactional返回null [英] @Transactional in bidirectional relation with Spring Data returns null

查看:55
本文介绍了与Spring Data双向关联的@Transactional返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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;
}

我正在使用JpaRepositories并将获取设置为急切.为什么有时当我从数据库中获取对象时却无法获取其子对象返回null.这取决于我从哪一侧添加对象.我已经使用Junit5编写了简单的测试:

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
    }
}

没有 @Transactional ,一切正常-我没有得到null.我在做什么错了?

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

推荐答案

您需要设置关系的两面以明确定义它.尝试在设置过程中添加 userEntity.setAccount(accountEntity),这样可以解决此问题.

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不会帮助您并且仅假设您设置了 a->即可.b ,它将在另一个实体内为您设置 b<-a .

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

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

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.

这篇关于与Spring Data双向关联的@Transactional返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆