Ich habe eine Anwendung für den Ruhezustand und eine JSF2-Anwendung, die auf den Implementierungsserver geht und plötzlich eine org.hibernate.AssertionFailure-Instanz auslöst. Ich werde den Stack-Trace und den Code sofort bereitstellen, aber hier sind zunächst vier wichtige Punkte:
Dies geschieht nur auf dem Deployment Server (Jboss & MySql unter Windows Server 2008.) Dies geschieht nicht auf meinem Entwicklungscomputer (Tomcat und MySql unter Windoes 7 Pro) und auch nicht in der Staging-Umgebung (Jboss und MySql unter Linux) .)
Beim Nachforschen scheint es, dass Leute diesen Fehler erhalten, wenn sie versuchen, ein Objekt einzufügen. Ich erhalte den Fehler, wenn ich eine einfache Abfrage mache. (verschiedene Abfragen, eigentlich, da der Fehler auf mehreren Seiten zufällig auftaucht.)
Der Fehler tritt nur ab und zu auf. Wenn ich einen Jboss-Neustart durchführe, verschwindet er, aber eine Zeit später kehrt er zurück. Es ist auch nicht konsistent, bei einigen Klicks ist es vorhanden, bei anderen nicht. Selbst wenn die Seite eine einfache Aktualisierung der Seite durchführt, wird sie einwandfrei angezeigt.
Ich verwende c3p0 (config unten)
Irgendeine Idee, was los ist
Die Code-Details:
Dies geschieht an einem Adressobjekt. Hier ist der volle 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>
Die Java-Klasse ist einfach:
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;
}
}
Die Konfiguration von 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>
Die verwendeten Versionen sind
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
Der volle Stacktrace
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)
Die Ausnahme:
org.hibernate.AssertionFailure: NULL-ID im Eintrag (Die Sitzung darf nicht geleert werden, wenn eine Ausnahme auftritt)
Teilt uns mit, dass die Sitzungsausnahme stattgefunden hat vorher der Punkt, an dem dieses org.hibernate.AssertionFailure
geworfen wird.
Um genau zu sein, wird org.hibernate.AssertionFailure
ausgelöst, wenn die session.flush()
stattfindet, nicht der Punkt, an dem der Fehler aufgetreten ist.
Das Obige ist eine Tatsache, daher ist eine mögliche Schlussfolgerung daraus: Etwas könnte unterdrückend die ursprüngliche Ausnahme sein.
Suchen Sie also nach other möglichen Fehlerpunkten: Eine save()
oder saveOrUpdate()
ist möglicherweise versucht, eine Entität mit einem null
-Feld zu persistieren wobei die Spalte in der Tabelle NOT NULL
ist?
TIP: Um beim Debuggen zu helfen, fügen Sie nach jeder Interaktion mit dem Session
-Objekt (z. B. session.flush()
, session.save(obj)
usw.) eine session.merge(obj)
hinzu. Dies führt hoffentlich dazu, dass org.hibernate.AssertionFailure
früher passiert wo das eigentliche Problem stattfindet. (Natürlich entfernen Sie nach dem Debuggen diese session.flush()
.)
In meinem Fall fand die real -Exception in einem try/catch {}
-Block statt, in dem die catch
die Exception unterdrückt hat (hat nicht erneut geworfen oder mich darüber gewarnt).
Ich würde für ein Parallelitätsproblem wetten, aber es kann auf verschiedenen Ebenen auftreten:
Abgesehen von diesen potenziellen Problemquellen würde ich c3p0 entfernen (vielleicht nur Gerüchte ...), da Ihr Stack DataSource
bereits ein Verbindungspooling mit dem Transaktionsmanager bereitstellt.
Der @asdcjunior hat richtig geantwortet. Etwas ist geschehen, bevor die Ausnahme ausgelöst wird.
In dieser Art von Situationen (bei Integrationsprüfungen kommt es häufig vor, wenn Sie eine einzelne Transaktion für einen Test ausführen (z. B. @Transaction-Annotation). Ich rufe die Methode auf:
session.clear()
Dies ist hilfreich, da alle 'schmutzigen' Objekte aus der aktuellen Sitzung entfernt werden. Wenn das nächste Flush ausgeführt wird, tritt das Problem nicht auf.
Beispielablauf:
Beispiel für einen korrekten Fluss:
Ich hoffe es hilft ;)
Sie schlagen wahrscheinlich einen Hibernate-Fehler. (Ich empfehle ein Upgrade auf mindestens Hibernate 3.3.2.GA.)
In der Zwischenzeit ist Hibernate besser, wenn Ihre ID nullfähig ist, sodass Hibernate immer den Unterschied zwischen einem neuen Objekt, das noch nicht in der Datenbank gespeichert wurde, und einem bereits in der Datenbank vorhandenen unterscheiden kann. Das Ändern des Typs von addressID
von long
in Long
wird das Problem möglicherweise umgehen.
Die von Ihnen bereitgestellte Stack-Ablaufverfolgung zeigt, dass das Problem in einer Abfrage angezeigt wird, da die Abfrage das Speichern von gepufferten Schreibvorgängen in die Datenbank erzwingt, bevor die Abfrage ausgeführt wird und der Schreibvorgang fehlschlägt, möglicherweise mit demselben Einfügeproblem, das andere Benutzer sehen.
Ich stand vor diesem Problem Ich füge nur try catch block hinzu und in catch block schrieb ich seesion.clear (); Jetzt kann ich mit dem Rest der Datensätze fortfahren, um sie in die Datenbank einzufügen
Herzliche Grüße: Shahid Hussain Abbasi
Problemfluss:
Sie haben viele Möglichkeiten, diesen Fehler zu mindern:
Beim Erstellen von session.getCurrentSession.refresh (entity) tritt derselbe Fehler auf, der mir eher nach einem Fehler aussieht als nach einem Problem mit meinem Code. Ich erhalte diesen Fehler in einem Komponententest, wenn ich zu Beginn eines Tests versuche, eine Entität zu aktualisieren, und diese Entität im Test-Setup erstellt wird (mit @Before von junit kommentiert). Was seltsam ist, ist, dass ich 3 Entitäten aus derselben Klasse mit zufälligen Daten zur selben Zeit und auf dieselbe Weise im Setup erstelle und die ersten beiden erstellten aktualisieren kann, aber die Aktualisierung für die letzte fehlschlägt. Wenn ich zum Beispiel 3 Entitäten Benutzer im Test-Setup erstelle, kann ich Benutzer1 und Benutzer2 aktualisieren und dies schlägt für Benutzer3 fehl. Ich konnte dies beheben, indem ich session.flush () am Ende des Codes hinzufügte, der die Entität im Setup erstellt. Ich bekomme keine Fehler und sollte es tun, aber ich kann nicht erklären, warum die zusätzliche Spülung erforderlich ist. Außerdem kann ich bestätigen, dass sich die Entitäten auch ohne Flush tatsächlich in der Test-DB befinden, da ich sie im Test abfragen kann, die Aktualisierungsmethode (Entität) jedoch weiterhin fehlschlägt.
Dies geschieht manchmal, wenn die Länge der Zeichenfolge größer ist als die von DB zulässige Länge.
DataIntegrityViolationException
übersetzt diese Ausnahme, die durch den Ruhezustand ein seltsames Verhalten darstellt.
Wenn Sie also eine Column
-Annotation für das String-Feld der Entität mit der angegebenen Länge haben und der tatsächliche Wert größer als diese Länge ist, wird die obige Ausnahme ausgelöst.
Ändern der Generatorklasse:
<generator class="identity" />
zu
<generator class="assigned" />
org.hibernate.AssertionFailure: NULL-ID im Eintrag (Die Sitzung darf nicht geleert werden, wenn eine Ausnahme auftritt)
Das ist uns gerade passiert und ich dachte, ich würde ein paar Details für die Nachwelt hinzufügen. Es stellt sich heraus, dass wir versucht haben, eine Entität mit einem doppelten Feld zu erstellen, das gegen eine Bedingung verstößt:
Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'
Diese Ausnahme wurde jedoch maskiert, weil der Ruhezustand versucht hatte, die Sitzung commit zu übergeben, obwohl das Erstellen fehlgeschlagen ist. Wenn der erstellte Fehler fehlgeschlagen ist, wurde die ID nicht gesetzt, daher der Assert-Fehler. In der Stapelverfolgung konnten wir feststellen, dass der Winterschlaf begangen wurde:
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.Java:480)
Es hätte die Sitzung zurücksetzen sollen, ohne sie zu begehen. Dies stellte sich als Problem bei unserer Rollback-Konfiguration heraus. Wir verwenden die alten XML-Konfigurationen und der Ausnahmepfad war falsch:
<prop key="create*">PROPAGATION_REQUIRED,-org.x.y.LocalException</prop>
Der LocalException
-Pfad war falsch und der Ruhezustand hat keinen Fehler ausgelöst (oder er wurde in der Startprotokollspur vergraben). Dies wäre wahrscheinlich auch der Fall, wenn Sie die Annotationen verwenden und nicht die richtigen Ausnahmen angeben:
// NOTE: that the rollbackFor exception should match the throws (or be a subclass)
@Transactional(rollbackFor = LocalException.class)
public void create(Entity entity) throws AnotherException {
Nachdem wir die Verdrahtung für den Ruhezustand behoben hatten, sahen wir die Ausnahme "Eintrag duplizieren" richtig und die Sitzung wurde ordnungsgemäß zurückgesetzt und geschlossen.
Ein weiteres Problem bestand darin, dass der Hibernate, wenn die AssertionFailure
geworfen wurde, eine Transaktionssperre in MySQL hielt, die dann von Hand getötet werden musste. Siehe: https://stackoverflow.com/a/39397836/179850
Dies hat nichts mit der gerade ausgeführten Abfrage zu tun. Dies löst nur die Spülung aus. An diesem Punkt versucht Hibernate der Entität eine Kennung zuzuweisen und scheint aus irgendeinem Grund fehlgeschlagen zu sein.
Könnten Sie versuchen, die Generatorklasse zu ändern:
<generator class="identity"/>
sehen Sie, ob das einen Unterschied macht. Haben Sie auch sichergestellt, dass für die bereitgestellte Datenbank die richtige Spalte für die automatische Erhöhung der Tabelle eingerichtet wurde?
Es klingt, als wäre Ihr Problem ähnlich wie dieses .
Ich habe auch die gleiche Ausnahme in der Hibernate-Konfigurationsdatei:
<property name="operateType" type="Java.lang.Integer">
<column name="operate_type" not-null="true" />
</property>
beim Übergeben eines Nullwerts am Objekt tritt eine Ausnahme auf
"org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",
Ich denke, der Grund dafür ist, dass Hibernaye die 'not-null'-Eigenschaft überprüft. Entfernen Sie also die' not-null'-Eigenschaft oder setzen Sie 'not-null' für 'false', um das Problem zu lösen.
OK, ich habe weiter nach anderen Antworten in diesem Thread gesucht. Aber am Ende, da wir einen Produktionsstermin hatten, musste ich die Notfallroutine wählen. Anstatt den Winterschlaf herauszufinden, tat ich diese beiden Dinge:
Eine jQuery-Bibliothek entfernt, mit der ich mich auf eines der Formulare konzentrierte. Ich habe dies getan, weil ich irgendwo gelesen habe, dass diese Art von Fehler auftreten kann, weil ein Formular einen Nullwert bereitstellt - die Null-ID in der Zeile verursacht wird. Ich hatte den Verdacht, dass die jQuery-Bibliothek möglicherweise nicht gut mit PrimeFaces zusammenarbeitet und zu einer Fehlfunktion der Form führt. Nur eine Ahnung.
Ich habe die durch den Ruhezustand implementierte Beziehung zwischen Benutzer und Adresse abgebrochen. (nur einer erforderlich, nicht einer zu vielen) und schrieb den Code bei Bedarf selbst. Glücklicherweise hat es nur eine Seite stark beeinflusst, daher war es nicht viel Arbeit.
Fazit: Wir sind live gegangen und die Anwendung läuft seit mehreren Tagen fehlerfrei. Diese Lösung mag also nicht schön sein - und ich bin nicht stolz auf mich -, aber ich habe eine laufende App und einen glücklichen Kunden.
Ich hatte den gleichen Fehler. In meinem Fall lag es daran, dass vor dieser Ausnahme eine Abfrage mit Ausnahme erstellt wurde. Ausnahme wird abgefangen und die Transaktion wird nicht im catch-Block zurückgesetzt. Dann benutze ich diese kaputte Transaktion in einer anderen Operation und nach ein paar Mal bekam ich die gleiche Ausnahme. Zuerst setze ich den Spülmodus auf manuell
public final Session getCurrentSession()
{
Session session = sessionFactory.getCurrentSession();
session.setFlushMode(FlushMode.MANUAL);
return session;
}
Dann bekam ich eine weitere Ausnahme, die mir erklärte, was tatsächlich geschah. Dann habe ich ein Transaktionsrollback im catch-Block meiner create-Methode durchgeführt. Und es hat mir geholfen.
org.hibernate.AssertionFailure: NULL-ID im Eintrag (Die Sitzung darf nicht geleert werden, wenn eine Ausnahme auftritt)
Sie erhalten diesen Fehler, während Sie die Speichermethode verwenden, wenn Sie den Versionsverlauf der Benutzeraktivität beibehalten und versuchen, die folgenden Werte festzulegen. setCreatedBy(1);
setModifiedBy(1);
setCreationDate();
setChangeDate();
} Sie erhalten den obigen Fehler, um dieses Problem zu lösen. Sie müssen die folgenden Spalten für die Tabelle erstellen.
Created_By
Modified_By
Creation_Date
Change_Date
wenn Sie denselben Fehler während der Update-Methode erhalten, um dieses Problem zu lösen Sie müssen lediglich die Update () -Methode in die merge () -Methode ändern, die es