-1

によって管理される次@Transactionalのメソッドがあります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();
}

TraceTraceEventHibernate によって管理されるエンティティです。

開発中にこのコードをテストしたとき、問題はまったくありませんでした。ただし、本番環境では、時々スローされます

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(およびpersisttraceEvent も) が汚れることを理解しています。そして、私が を呼び出すとcreate(traceEvent)、それも試みてpersist、Hibernate セッションに同じオブジェクトを追加することがあります。

例外が発生する理由と、このようにランダムな間隔で発生するのはなぜですか?

エンティティの編集

@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;
4

1 に答える 1

1

最後に Hibernate を使用してからしばらく時間が経ちましたが、問題は難しい性質のものであるため、さまざまなオプションについて説明します。

  • Traceオブジェクトにはオプションがあるので、セットに を追加して呼び出すCascade.Allだけで十分ではありませんか? 現在の私の印象では、セッションが閉じると、オブジェクトを保存しようとします。または、セットを変更しないでください。を保存するだけです。もう使用されることはないので、変更しても意味がありません。次回使用するときは、おそらくデータベースからロードされるでしょう。上記のすべての動作は構成に依存する可能性がありますが、一見の価値があるかもしれません。TraceEventsession.save(trace)TraceTraceEventTrace

  • ある種の休止状態キャッシュを使用していますか? Traceオブジェクトが最新バージョンではない可能性がありますか?

  • どのようTraceEventに作成されますか?このオブジェクトが切り離されている可能性があります (以前のリクエストでロードされ、現在再利用されていますか?) 可能性は低いと思われますが、確認してください。

  • これは、多くの場所から呼び出すことができる関数のようです (つまり、ユーザーのアクションを記録するために)。他の場所の 1 つが同じセッションを使用していて、それを変更している可能性はありますか?

  • 多くの場所から呼び出されたと仮定すると、ログからエラーを特定のビジネス機能 (ユーザーがそのリンク/ボタンをクリックしたときなど) にリンクできましたか?

  • EventListener他のすべてが失敗した場合は、次に本番環境を更新するときに、またはon persist イベントを追加してみませんかInterceptor(このエラーを簡単に再現できないことは理解しています)。NonUniqueObjectException追加のログ情報を出力してから再スローする可能性があるのをキャッチする単純なものです。

于 2013-07-19T20:25:58.793 に答える