我有以下@Transactional
由 a 管理的方法HibernateTransactionManager
:
@Transactional(rollbackFor = NoActiveTraceException.class)
public void insertTraceEvent(TraceEvent traceEvent) throws NoActiveTraceException {
Trace trace = traceDao.findActiveForNumber(traceEvent.getSourceParty());
if (trace == null) {
throw new NoActiveTraceException(traceEvent.getSourceParty()); // custom
} else {
traceEvent.setTrace(trace);
trace.getTraceEvents().add(traceEvent); // returns set to which I can add
// there is a Cascade.All on the @OneToMany set
traceDao.create(traceEvent);
}
}
// ...in traceDao
@Override
public Long create(TraceEvent traceEvent) {
getCurrentSession().persist(traceEvent);
return traceEvent.getTraceEventId();
}
Trace
并且TraceEvent
是由 Hibernate 管理的实体。
当我在开发过程中测试这段代码时,我从来没有遇到任何问题。但是在生产中,它会不时抛出
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [myobject#2664]
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:136) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:208) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:151) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:78) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:843) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:818) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:822) ~[hibernate-core-4.1.9.Final.jar:4.1.9.Final]
at com.package.model.dao.impl.TraceDaoHibernateImpl.create(TraceDaoHibernateImpl.java:116) ~[TraceDaoHibernateImpl.class:na]
当试图坚持它时。我想不出会导致这种情况的 prod 和 dev 之间的任何区别。此过程独立于一切(并在事务中运行)。
我知道,一旦我调用.add(traceEvent)
,它就会弄脏PersistentSet
(并且可能会persist
弄脏 traceEvent)。然后当我调用它时create(traceEvent)
,它也可能会尝试persist
它,从而在 Hibernate Session 中添加相同的对象。
为什么会发生异常,为什么会以这样的随机间隔发生?
编辑实体
@Entity
@Table(name = "TRACE_EVENT")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class TraceEvent {
@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
@Column(name = "trace_event_id")
private Long traceEventId;
@Column(nullable = false)
private Calendar transmissionDate;
@Column(nullable = false)
private String sourceParty;
@Column
private String destinationParty;
@ManyToOne(optional = false)
@JoinColumn(name = "trace_id")
private Trace trace;
和
@Entity
@Table(name = "TRACE")
public class Trace {
@Id
@GenericGenerator(name = "generator", strategy = "increment")
@GeneratedValue(generator = "generator")
@Column(name = "trace_id")
private Long traceId;
@Column(nullable = false)
private String number;
@Column(nullable = false)
private Calendar startDate;
@Column
private Calendar endDate;
@Column(nullable = false)
private Boolean isActive = false; // default value of false
// USED TO BE CASCADE.ALL
@OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE}, mappedBy = "trace")
private Set<TraceEvent> traceEvents = new HashSet<>();
@ManyToOne
private Account account;