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

时间:2018-11-01 23:36:13

标签: java hibernate spring-data-jpa spring-transactions

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

module.exports = {
  entry: ["./src/index.js"],
  module: {
    rules: [
      { test: /\.(js|jsx)$/, exclude: /node_modules/, use: ["babel-loader"] },
      {
        test: /\.(jpg|png|gif|ico)$/,
        use: {
          loader: "file-loader",
          options: { name: "[path][name].[hash].[ext]" }
        }
      }
    ]
  },
  resolve: { extensions: ["*", ".js", ".jsx"] },
  output: {
    path: __dirname + "/dist",
    publicPath: "/",
    filename: "[name].[hash].js"
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({ hash: false, template: "src/index.html" }),
    new DashboardPlugin(),
    new CopyWebpackPlugin([
      {
        from: "src/components/Assets/BookingBar.js",
        to: "assets/BookingBar.js"
      }
    ]),
    new BundleAnalyzerPlugin()
  ],
  devServer: {
    contentBase: "./dist",
    hot: true,
    historyApiFallback: true,
    port: 4000
  }
};

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

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

在没有@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 } } 的情况下,一切正常-我没有得到null。 我在做什么错了?

2 个答案:

答案 0 :(得分:2)

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

休眠不会仅仅因为您设置了a -> b而承担任何责任,而是会在另一个实体中为您设置b <- a

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

答案 1 :(得分:1)

这是因为您没有在userEntity中设置帐户。请尝试如下操作:

userEntity.setAccount(accountEntity);