我遇到了与我的数据库保持一对多,多对一的双向关系的问题,我无法弄清楚我到底做错了什么。希望有人可以帮助我。
我的数据库中有2个实体,声明如下:
class Lot {
@OneToMany(targetEntity = Request.class, mappedBy = "lot", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private Set<Requests> requests;
}
class Request{
@ManyToOne(optional = true, fetch = FetchType.EAGER)
@JoinColumn(name = "fk_lot")
private Lot lot;
}
问题出现在这里:
class RequestManagerImpl{
// compose Request r object
requestId = saveRequest(r).getId();
// check to see if we need to create a parent object
LotType lot = createRequestInput.getLot();
if(lot != null){
addRequestToLot(Lists.newArrayList(r), lot);
}
}
class LotManagerImpl {
@Override
public Lot addRequestsToLot(List<Request> requests, Lot lot) {
if (lot != null && requests != null && !requests.isEmpty()) {
for (Request request : requests) {
lot.addRequest(request);
}
Lot lotValue = lotDAO.saveOrUpdate(lot);
if (lotValue != null) {
updateLotStatusByRequestsStatus(lotValue);
}
return lotValue;
}
}
class LotDAO {
@Override
public Lot saveOrUpdate(Lot lot) {
if (em.contains(lot)) {
em.merge(lot);
} else {
em.persist(lot);
}
return lot;
}
}
class RequestDAO {
@Transactional(propagation = Propagation.REQUIRES_NEW)
Request saveRequest(Request request);
}
em.persist返回以下stacktrace:
Caused by: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: disp.entities.Request
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:147)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:771)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:458)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:383)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:491)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:423)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:386)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:445)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:281)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:182)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:780)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:765)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at .proxy.$Proxy78.persist(Unknown Source)
at disp.dao.impl.LotDAOImpl.saveOrUpdate(LotDAOImpl.java:123)
答案 0 :(得分:1)
你可能会错过这里的oneToMany映射的魔力
这条线
requestId = saveRequest(r).getId();
是不可能的,因为它依赖于Lot。
如果您将请求添加到批次并保存批次,则会自动保存请求作为映射的结果。
答案 1 :(得分:0)
我实际上自己发现了这个问题。
问题出在RequestDAO :: saveRequest方法中,事务被声明为Propagation.REQUIRES_NEW。这是在新事务中创建请求(子对象),稍后在保存它时从批(父)分离。
我只需将其更改为Propagation.REQUIRED即可使用现有事务提交父对象和子对象。