web-dev-qa-db-ja.com

org.hibernate.AssertionFailure:エントリ内のnull ID(例外が発生した後にセッションをフラッシュしないでください)

休止サーバーとJSF2アプリケーションがデプロイメントサーバーに移動し、突然org.hibernate.AssertionFailure:null idをスローします。すぐにスタックトレースとコードを提供しますが、最初に4つの重要な問題があります。

  1. これは展開サーバー(Windows Sever 2008で実行されるJBossおよびMySql)でのみ発生します。開発マシン(Windoes 7 Proで実行されるTomcatおよびMySql)では発生せず、ステージング環境(Linuxで実行されるJbossおよびMySqlでも発生しません) )

  2. これを調査すると、オブジェクトを挿入しようとするとこのエラーが発生するようです。しかし、単純なクエリを実行するとエラーが発生します。 (実際には、エラーが複数のページにランダムに表示されるため、さまざまなクエリが実行されます。)

  3. エラーはたまにしかヒットしません。 Jbossの再起動を行うと消えますが、しばらくすると戻ります。また、一貫性がなく、一部のクリックでは存在し、他のクリックでは存在しません。ヒットした場合でも、ページを簡単に更新すると、正常に戻ります。

  4. 私はc3p0を使用しています(下の設定)

何が起こっているのでしょうか?

コードの詳細:

これはアドレスオブジェクトで発生します。完全なhbmは次のとおりです。

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.idex.auctions.model">
<class name="Address" table="address" lazy="true">
  <id name="addressID" column="AddressID">
        <generator class="native"/>            
  </id>

  <property name="street" column="street"/> 
  <property name="city" column="city"/> 
  <property name="Zip" column="Zip"/> 
  <property name="state" column="state"/> 
  <property name="region" column="region"/> 
  <property name="country" column="country"/> 

  <many-to-one name="user" 
       class="com.idex.auctions.model.User" 
       column="userid" 
       unique="true" 
       cascade="save-update"/>
 </class> 
</hibernate-mapping>

Javaクラスは簡単です:

public class Address implements Serializable {
private static final long serialVersionUID = 7485582614444496906L;

private long addressID;
private String street;
private String city;
private String Zip;
private String state;
private String region;
private String country;
private User user;

public Address() {

}
public long getAddressID() {
    return addressID;
}
public void setAddressID(long addressID) {
    this.addressID = addressID;
}
public String getStreet() {
    return street;
}
public void setStreet(String street) {
    this.street = street;
}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getZip() {
    return Zip;
}
public void setZip(String Zip) {
    this.Zip = Zip;
}
public String getState() {
    return state;
}
public void setState(String state) {
    this.state = state;
}
public String getRegion() {
    return region;
}
public void setRegion(String region) {
    this.region = region;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public User getUser() {
    return user;
}
public void setUser(User user) {
    this.user = user;
}

}

C3p0の構成:

<property name="hibernate.c3p0.acquire_increment">1</property> 
<property name="hibernate.c3p0.idle_test_period">1000</property> 
<property name="hibernate.c3p0.max_size">20</property>  
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">1800</property>
<property name="hibernate.c3p0.max_statements">0</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

使用されるバージョンは

hibernate3.jar

c3p0-0.9.1.2.jar

myfaces-api-2.1.4.jar

myfaces-impl-2.1.4.jar

mysql-connector-Java-5.1.20-bin.jar

完全なスタックトレース

org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry 
    (don't flush the Session after an exception occurs)
org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(
                                          DefaultFlushEntityEventListener.Java:78)
org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(
                                          DefaultFlushEntityEventListener.Java:187)
org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(
                                          DefaultFlushEntityEventListener.Java:143)
org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(
                                          AbstractFlushingEventListener.Java:219)
org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(
                                          AbstractFlushingEventListener.Java:99)
org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(
                                          DefaultAutoFlushEventListener.Java:58)
org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.Java:997)
org.hibernate.impl.SessionImpl.list(SessionImpl.Java:1142)
org.hibernate.impl.QueryImpl.list(QueryImpl.Java:102)
com.idex.auctions.manager.DatabaseManager.getAllObjects(DatabaseManager.Java:464)
com.idex.auctions.ui.NavBean.gotoHome(NavBean.Java:40)
Sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Java.lang.reflect.Method.invoke(Unknown Source)
javax.el.BeanELResolver.invokeMethod(BeanELResolver.Java:735)
javax.el.BeanELResolver.invoke(BeanELResolver.Java:467)
javax.el.CompositeELResolver.invoke(CompositeELResolver.Java:246)
org.Apache.el.parser.AstValue.getValue(AstValue.Java:159)
org.Apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.Java:189)
org.Apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.getValue(
                                          ContextAwareTagValueExpression.Java:96)
javax.faces.component._DeltaStateHelper.eval(_DeltaStateHelper.Java:246)
javax.faces.component.UIOutcomeTarget.getOutcome(UIOutcomeTarget.Java:50)
org.Apache.myfaces.shared.renderkit.html.HtmlRendererUtils.getOutcomeTargetHref(
                                          HtmlRendererUtils.Java:1542)
org.Apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.renderOutcomeLinkStart(
                                          HtmlLinkRendererBase.Java:908)
org.Apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.encodeBegin(
                                          HtmlLinkRendererBase.Java:143)
javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.Java:502)
javax.faces.component.UIComponent.encodeAll(UIComponent.Java:744)
javax.faces.component.UIComponent.encodeAll(UIComponent.Java:758)
javax.faces.component.UIComponent.encodeAll(UIComponent.Java:758)
org.Apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(
                                    FaceletViewDeclarationLanguage.Java:1900)
org.Apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.Java:285)
com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(
                                    PrettyViewHandler.Java:163)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.Java:59)
org.Apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(
                                    ResourceViewHandlerWrapper.Java:93)
com.idex.auctions.ui.CustomViewHandler.renderView(CustomViewHandler.Java:98)
org.Apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.Java:115)
org.Apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.Java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.Java:199)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.Java:126)
com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.Java:118)
40
Herzog

例外:

org.hibernate.AssertionFailure:エントリ内のnull id(例外が発生した後にセッションをフラッシュしないでください)

セッション例外がの前に発生したことを示しますこのorg.hibernate.AssertionFailureがスローされるポイント。

正確には、session.flush()が発生したときにエラーが発生したポイントではなく、org.hibernate.AssertionFailureがスローされます。

上記は事実であるため、結論として考えられるのは、何かが抑制元の例外である可能性があることです。

その他エラーの可能性のあるポイントを探してください:save()またはsaveOrUpdate()はおそらくnullフィールドを持つエンティティを永続化しようとしていますテーブルの列NOT NULLは何ですか?


ヒント:デバッグを支援するために、Sessionオブジェクトとのすべての対話の後にsession.flush()を追加してみてください(例session.save(obj)session.merge(obj)など)。 org.hibernate.AssertionFailureをより早く、実際の問題が発生している場所により近い場所で発生させることを願っています。 (もちろん、デバッグ後、これらのsession.flush()を削除します。)


私の場合、real例外がtry/catch {}ブロック内で発生し、そこでcatchが例外を抑制しました(再スローも警告もしませんでした)。

40
acdcjunior

私は並行性の問題に賭けますが、異なるレベルで発生する可能性があります。

これらの潜在的な問題の原因とは別に、スタックがトランザクションマネージャーと統合された接続プーリングでDataSourceを既に提供しているので、c3p0(おそらく噂...)を削除します。

11
Yves Martin

@asdcjuniorは正解です。例外がスローされる前に何かが発生しました。

そのような状況では(1つのテストで単一のトランザクションを処理するときに統合テストで頻繁に発生します-@Transactionアノテーションなど)、メソッドを呼び出しています。

session.clear()

すべての「ダーティ」オブジェクトが現在のセッションから削除され、次のフラッシュが実行されたときに問題が発生しないため、役立ちます。

フローの例:

  • 割り当てエンティティを挿入します(単一の割り当てのみが存在する可能性がある制約を持つ多対多の関係)->すべてOK
  • 同じ割り当てエンティティをもう一度挿入します->すべてがOK、この場合はコントローラが何らかの悪いリクエスト例外を返します、SpringはIntegrityViolationExceptionをスローします->すべてが正常に見えるテスト
  • リポジトリを取得し、findAll()。size()を実行して、存在する割り当ての数を確認し、割り当てが1つだけであることを確認します->言及された例外がスローされます; /何が起こったのですか?セッションにはまだダーティなオブジェクトが存在し、通常はセッションが破棄されます(コントローラーの戻りエラー)が、ここではデータベースに関する次のアサーションがあるため、ここでの解決策は次のdb関連のメソッド実行の前に追加のsession.clear()です

正しいフローの例:

  • 割り当てエンティティを挿入します
  • 同じ割り当てエンティティを挿入します
  • session.clear()
  • リポジトリを取得し、findAll()。size()を実行します

それが役に立てば幸い ;)

6
Przemek Nowak

おそらく、いくつかのHibernateのバグが発生しています。 (少なくともHibernate 3.3.2.GAにアップグレードすることをお勧めします。)

一方、Hibernateは、IDがNULL可能であれば、データベースにまだ保存されていない新しいオブジェクトと既にデータベースにあるオブジェクトとの違いを常に認識できるようになると、パフォーマンスが向上します。 addressIDのタイプをlongからLongに変更すると、おそらくこの問題を回避できます。

提供されたスタックトレースは、クエリがバッファされた書き込みをクエリが実行される前にデータベースにフラッシュすることを強制し、書き込みが失敗するため、クエリで問題が発生していることを示しています。おそらく他の人が見ている同じ挿入問題があります。

3
Old Pro

この問題に直面していたのは、try catchブロックを追加するだけで、catchブロックにseesion.clear()を記述しただけです。これで、残りのレコードを続行してデータベースに挿入できます

敬具:シャヒドフセインアッバシ

問題の流れ:

  1. 新しい一時エンティティインスタンス(ここではAddressインスタンス)を作成します
  2. データベースに保存します(保存、マージ、またはHibernate Session/JPA EntityManagerで保存)
  3. エンティティ識別子はデータベースによって生成されるため、Hibernateは生成されたIDを取得するためにデータベース挿入をトリガーする(セッションをフラッシュする)
  4. 挿入操作は例外(またはセッションで保留中のフラッシュされていない変更)をトリガーします
  5. 例外を(それを伝播することなく)キャッチし、実行フローを再開します(この時点で、セッションにはまだIDのない非永続インスタンスが含まれています。問題は、Hibernateがインスタンスを管理対象と見なしているようですが、インスタンスが管理対象オブジェクトとして破損していることですIDが必要です)
  6. 作業単位の最後に到達すると、現在のトランザクションがコミットされる前にセッションが自動的にフラッシュされます。セッションには破損したインスタンスが含まれるため、フラッシュはアサーション障害で失敗します

このエラーを軽減する多くの可能な方法があります:

  • 最も単純なものであり、休止状態は「例外の発生後にセッションをフラッシュしないでください」という意味です。永続化例外の後、すぐに現在のトランザクションを放棄してロールバックします。
  • エラーをキャッチした後、破損したインスタンスをセッションから手動で削除(JPA:デタッチ)します(ポイント5で、エラーがエンティティ挿入自体ではなく別の保留中の変更によってトリガーされた場合、これは役に立ちません)
  • データベースがID生成を処理しないようにします(UUIDまたは分散ID生成システムを使用します。この場合、最終フラッシュは休止状態のアサーションエラーではなく、新しいインスタンスの永続性を妨げる実際のエラーをスローします)
1
Gab

Session.getCurrentSession.refresh(entity)を作成すると同じエラーが発生しますが、コードの問題ではなく、バグのように見えます。ユニットテストでこのエラーが発生します。テストの開始時にエンティティを更新しようとすると、そのエンティティがテスト設定で作成されます(junitの@Beforeアノテーションが付けられます)。奇妙なのは、同じクラスから3つのエンティティをランダムデータで同時にセットアップで作成し、作成された最初の2つを更新できるが、最後の1つで更新が失敗することです。たとえば、テストセットアップで3つのエンティティユーザーを作成した場合、user1とuser2を更新できますが、user3で失敗します。セットアップでエンティティを作成するコードの最後にsession.flush()を追加することで、これを解決できました。エラーは表示されず、表示されるはずですが、追加のフラッシュが必要な理由を説明できません。また、テストではクエリを実行できますが、refresh(entity)メソッドが失敗するため、エンティティがフラッシュなしでも実際にテストDBにあることを確認できます。

0
P Sh

これは、文字列の長さがDBで許可されている長さより大きい場合に発生することがあります。

DataIntegrityViolationExceptionは、この例外に変換されます。これは、休止状態による奇妙な動作です。

そのため、指定された長さのエンティティのStringフィールドにColumn注釈があり、実際の値がその長さより大きい場合、上記の例外がスローされます。

参照: https://developer.jboss.org/thread/186341?_sscc=t

0
Nikhil Sahu

ジェネレータークラスの変更:

<generator class="identity" />

<generator class="assigned" />
0
William

org.hibernate.AssertionFailure:エントリ内のnull id(例外が発生した後にセッションをフラッシュしないでください)

これは私たちに起こったことであり、後世のためにいくつかの詳細を追加すると思いました。条件に違反する重複フィールドを持つエンティティを作成しようとしていたことがわかりました。

Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'

ただし、作成が失敗したにもかかわらず、休止状態がセッションをcommitしようとしていたため、この例外はマスクされていました。作成が失敗した場合、IDが設定されなかったため、アサートエラーが発生しました。スタックトレースでは、休止状態がコミットされていることがわかりました。

at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.Java:480)

セッションをコミットするのではなく、ロールバックする必要がありました。これは、ロールバック構成の問題であることが判明しました。古いXML設定を使用しており、例外パスが正しくありませんでした。

<prop key="create*">PROPAGATION_REQUIRED,-org.x.y.LocalException</prop>

LocalExceptionパスは正しくなく、休止状態はエラーをスローしませんでした(または、起動ログの噴出に埋もれていました)。これはおそらく、注釈を使用していて、正しい例外を指定しない場合にも当てはまります。

// NOTE: that the rollbackFor exception should match the throws (or be a subclass)
@Transactional(rollbackFor = LocalException.class)
public void create(Entity entity) throws AnotherException {

休止状態の配線を修正すると、「重複エントリ」例外が正しく表示され、セッションは適切にロールバックされて閉じられました。

これに対するもう1つの問題は、休止状態がAssertionFailureをスローしたときに、MySQLでトランザクションロックを保持していたため、手動で強制終了する必要があったことです。参照: https://stackoverflow.com/a/39397836/17985

0
Gray

これは、実行中のクエリとは関係ありません。これはフラッシュをトリガーするだけです。この時点で、Hibernateはエンティティに識別子を割り当てようとしていますが、何らかの理由で失敗したようです。

ジェネレータークラスを変更してみてください:

<generator class="identity"/>

それが違いを生むかどうかを確認してください。また、展開したデータベースのテーブルに正しい自動インクリメント列が設定されていることを確認しましたか?

あなたの問題は this one に似ているようです。

0
Alex Barnes

Hibernate設定ファイルにも同じ例外があります。

<property name="operateType" type="Java.lang.Integer">
        <column name="operate_type" not-null="true" />
 </property>

オブジェクトにnull値を渡すと、例外が発生します

 "org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",

Hibernayeが「not-null」プロパティをチェックするので、「not-null」プロパティを削除するか、「not-null」を「false」に設定することで問題が解決するためだと思います。

0
waveopera

OK、私はこのスレッドの他の答えに基づいて特に研究を続けました。しかし、最終的には、生産期限に間に合わなかったため、緊急時の敗走を選択する必要がありました。そこで、休止状態を把握する代わりに、次の2つのことを行いました。

  1. フォームの1つにフォーカスするために使用していたjQueryライブラリを削除しました。このようなバグは、null値をポストするフォームが原因で発生する可能性があることをどこかで読んだためです。 jQueryライブラリーがPrimeFacesにうまく適合せず、何らかの形で誤動作する可能性があると思われます。ただの予感。

  2. ユーザーとアドレスの間に持っていた休止状態の実装関係を削除しました。 (1対多ではなく、1つだけが必要です)、必要なときに自分でコードを作成しました。幸いなことに、それは1つのページだけに大きな影響を与えたので、たいした作業ではありませんでした。

結論:私たちはライブになり、アプリケーションはエラーなしで数日間実行されました。したがって、このソリューションはきれいではないかもしれません-そして私は自分自身を誇りに思っていません-しかし、私は実行中のアプリと幸せなクライアントを持っています。

0
Herzog

同じエラーが発生しました。私の場合は、この例外の前にcreate query with exceptionを実行したためです。例外がキャッチされ、catchブロックでトランザクションをロールバックしません。次に、この壊れたトランザクションを他の操作で使用し、数時間後に同じ例外が発生しました。最初に、フラッシュモードを手動に設定します

public final Session getCurrentSession()  
{
    Session session = sessionFactory.getCurrentSession();
    session.setFlushMode(FlushMode.MANUAL);
    return session;
}

その後、別の例外があり、実際に何が起こったのかを説明してくれました。次に、作成メソッドのcatchブロックでトランザクションのロールバックを行いました。そしてそれは私を助けました。

0
tomasomsk

org.hibernate.AssertionFailure:エントリ内のnull ID(例外が発生した後にセッションをフラッシュしないでください)

ユーザーアクティビティのバージョン履歴を維持し、次の値を設定しようとすると、saveメソッドの使用中にこのエラーが発生しますsetCreatedBy(1); setModifiedBy(1); setCreationDate(); setChangeDate();}これを解決するために上記のエラーが発生します。テーブルの列。

Created_By Modified_By Creation_Date Change_Dateこの問題を解決するためにUpdateメソッドで同じエラーが発生する場合は、Update()メソッドをmerge()メソッドに変更する必要があります。

0
iragond