我有这两个豆子:
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的一个问题吗?
答案 0 :(得分:1)
首先,您需要在subscription
对象中设置channel
,该对象引用它并且值不可为空。这是你收到的例外的原因。这种类型的映射在AgentSubscription
表中创建OutputChannel
外键,因此您始终必须设置它,级联与否。 Hibernate不会执行任何自动设置或某种自动设置。
因此,就您的代码而言,添加
channel.setSubscription(subscription);
在DAO插入调用之前应该解决问题。这样,当entityManager.persist(subscription)
(或者你坚持)被调用时,channel
也将被保留。