持久化一对多单向关系时,外键为null

时间:2016-01-26 01:42:53

标签: hibernate junit

上下文

我有2个实体,映射如下:

@Entity
public class User {

@Id
private String mail;

@OneToMany(cascade={CascadeType.REMOVE} fetch=FetchType.EAGER)
private Set<Food> foods;

和食物:

@Entity
public class Food{

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

我的测试:

@Test   
public void testPersistUserWithFood() throws Exception{
  //I create and persist the user
  User user = new User ("@someone");
  Session sess = HibernateUtil.getSessionFactory().openSession();
  Transaction tx = sess.beginTransaction();
  sess.save(user);
  tx.commit();
  sess.close();      

  //Now I create de food and set the relation in object schema
  Food foo = new Food();
  user.getFoods.add(foo);

  //I persist the food in the same way than user, with session, transaction and so on.

  //Then I retrieve the user from DB
  sess = HibernateUtil.getSessionFactory().openSession();
  User userRetrieved =(User) sess.createCriteria(User.class)
                 .add(Restrictions.idEq("@someone")).uniqueResult();
  sess.close();

  //Finally assert
  assertEquals(user.getFoods(), userRetrieved.getFoods());

}

问题

测试失败,因为调用:userRetrieved.getFoods()返回空列表。 当我进行了调试时,我看到表格中的id_User foreing列始终为null。 如果关系是oneToMany双向,则列id_User不为null,因为我在Food类中添加了用户属性。

感谢您的帮助!

注意:我使用的是hibernate 4.3.8,jUnit 4和java 8

3 个答案:

答案 0 :(得分:0)

userRetrieved.getFoods() return a null list.

这意味着当您添加食物时,用户不会更新。

...
...

  //Now I create de food and set the relation in object schema

  //I persist the food in the same way than user, with session, transaction and so on.
  Session sess = HibernateUtil.getSessionFactory().openSession();
  Transaction tx = sess.beginTransaction();

  Food foo = new Food();
  user.getFoods.add(foo);

  sess.update(user);    //are you updating User as well like this?
  sess.save(foo);
  tx.commit();
  sess.close();
...
...

P.S。如果它不起作用,那么请发布完整的代码,以显示您如何持久保存所有实体。

答案 1 :(得分:0)

您有id_Usernull,因为此处新id对象中null等于Food

Food foo = new Food();
user.getFoods().add(foo);

要解决此问题,您需要将新的Foo对象保存到Hibernate,为其分配id。之后,将Foo保存到foods集合中。或者您可以使用cascade = CascadeType.ALL来Hibernate使用父

保存新的子对象
@OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Food> foods;

答案 2 :(得分:-1)

谢谢大家,我解决了我的问题,这是代码:

一个实体

@Entity
public class User {

@Id
private String mail;

@OneToMany(cascade={CascadeType.REMOVE} fetch=FetchType.EAGER)
@JoinColumn(name="id_User")
private Set<Food> foods;

许多实体

@Entity
public class Food{

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;

测试

 @Test   
 public void testPersistUserWithFood() throws Exception{

  //I create and persist the user
  User user = new User ("@someone");
  Session sess = HibernateUtil.getSessionFactory().openSession();
  Transaction tx = sess.beginTransaction();
  sess.save(user);
  tx.commit();
  sess.close();      

  //Now I create de food and set the relation in object schema
  Food foo = new Food();
  user.getFoods.add(foo);

  //I persist the food in the same way than user, with session, transaction and so on.

  //Hibernate don´t know that the user contains the food when persist the
  // food, because the relationship is unidirectional, therefore:
  sess = HibernateUtil.getSessionFactory().openSession();
  tx = sess.beginTransaction();
  sess.update(user);
  tx.commit();
  sess.close();  

  //Then I retrieve the user from DB
  sess = HibernateUtil.getSessionFactory().openSession();
  User userRetrieved =(User) sess.createCriteria(User.class)
             .add(Restrictions.idEq("@someone")).uniqueResult();
  sess.close();


  //Finally assert
  assertEquals(user.getFoods(), userRetrieved.getFoods());

}

要点:

  1. 保存用户
  2. 节省食物
  3. 更新用户
  4. 非常感谢!