为了与JPA和Hibernate保存OneToMany关系

时间:2014-06-26 13:27:25

标签: java hibernate jpa-2.0

我有这两个豆子:

public class AgentSubscription {

//...
  @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, mappedBy = "subscription")
  @Fetch(FetchMode.SUBSELECT)
  @OrderBy("ID_SUBSCRIPTION")
  private List<OutputChannel> channels;
//...
}

public class OutputChannel {
//...
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "ID_SUBSCRIPTION", nullable = false)
  private AgentSubscription subscription;
//...
}

如果我们尝试使用此方法:

  @Transactional
  public void addChannel(AgentSubscription subscription, OutputChannel channel)
  {
    try
    {
      List<OutputChannel> channels = new ArrayList<OutputChannel>();
      channels.add(channel);
      subscription.setChannels(channels);
      subscription = agentSubscriptionDao.insert(subscription);
    }
    catch (Exception e)
    {
      LOGGER.error("Unable to add channel to subscription " + subscription.getSubscriptionId());
    }
  }

我们得到了这个例外:

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.domain.agent.beans.channel.OutputChannel.subscription

Hibernate不应该在频道之前保存订阅吗?这可能是CascadeType的一个问题吗?

1 个答案:

答案 0 :(得分:1)

首先,您需要在subscription对象中设置channel,该对象引用它并且值不可为空。这是你收到的例外的原因。这种类型的映射在AgentSubscription表中创建OutputChannel外键,因此您始终必须设置它,级联与否。 Hibernate不会执行任何自动设置或某种自动设置。 因此,就您的代码而言,添加

channel.setSubscription(subscription);
在DAO插入调用之前

应该解决问题。这样,当entityManager.persist(subscription)(或者你坚持)被调用时,channel也将被保留。