J'ai une application Hibernate et JSF2 qui se rend sur le serveur de déploiement et lance soudainement une exception org.hibernate.AssertionFailure: null id. Je vais fournir la trace de la pile et le code immédiatement, mais voici quatre problèmes importants en premier:
Cela ne se produit que sur le serveur de déploiement (Jboss & MySql sous Windows Server 2008). Cela ne se produit pas sur ma machine de développement (Tomcat et MySql sous Windoes 7 Pro) ni avec l'environnement de transfert (Jboss et MySql sous Linux .)
En recherchant cela, il semble que les gens obtiennent cette erreur en essayant d'insérer un objet. Mais je reçois l'erreur lorsque je fais une requête simple. (différentes requêtes, en fait, lorsque l'erreur apparaît sur plusieurs pages au hasard.)
L'erreur ne frappe que de temps en temps. Si je fais un redémarrage Jboss, il disparaîtra, mais le temps reviendra plus tard. En outre, ce n'est pas cohérent, sur certains clics c'est là, sur d'autres ce n'est pas. Même lorsque le message est affiché, lorsque je fais un simple rafraîchissement de la page, tout se passe bien.
J'utilise c3p0 (config ci-dessous)
Une idée de ce qui se passe?
Les détails du code:
Cela se produit sur un objet adresse. Voici le hbm complet:
<?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>
La classe Java est simple:
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;
}
}
La configuration 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>
Les versions utilisées sont
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
La pile complète
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)
Je parierais pour un problème de concurrence, mais cela peut se produire à différents niveaux:
Outre ces sources potentielles de problèmes, je supprimerais c3p0 (peut-être simplement des rumeurs ...) car votre pile fournit déjà DataSource
avec la mise en commun des connexions intégrée au gestionnaire de transactions.
Le @asdcjunior a répondu correctement. Quelque chose s'est passé avant que l'exception soit levée.
Dans ce genre de situation (cela se produit souvent lors de tests d'intégration lorsque vous traitez avec une transaction unique pour un test - par exemple, l'annotation @Transaction), j'appelle la méthode:
session.clear()
Cela aide car tous les objets "sales" sont supprimés de la session en cours. Ainsi, lors de l'exécution du rinçage suivant, le problème n'apparaît pas.
Exemple de flux:
Exemple de flux correct:
J'espère que ça aide ;)
Vous rencontrez probablement un bogue Hibernate. (Je vous recommande de mettre à niveau vers au moins Hibernate 3.3.2.GA.)
Pendant ce temps, Hibernate fait mieux lorsque votre identifiant peut être annulé, afin qu’Hibernate puisse toujours faire la différence entre un nouvel objet qui n’a pas encore été conservé dans la base de données et un autre qui est déjà dans la base de données. Changer le type de addressID
de long
à Long
résoudra probablement le problème.
La trace de pile que vous avez fournie montre que vous voyez le problème sur une requête, car elle oblige les écritures mises en tampon à être vidées dans la base de données avant que la requête ne soit exécutée et que l'écriture échoue, probablement avec le même problème d'insertion que d'autres personnes voient.
Je faisais face à ce problème Je viens d’ajouter try catch et dans catch block j’ai écrit seeion.clear (); Maintenant je peux continuer avec le reste des enregistrements à insérer dans la base
Cordialement, Shahid Hussain Abbasi
Flux de problème:
Vous avez plusieurs façons possibles d'atténuer cette erreur:
Parfois, cela se produit lorsque la longueur de la chaîne est supérieure à celle autorisée par la base de données.
DataIntegrityViolationException
traduit cette exception qui est un comportement étrange de la part de Hibernate.
Ainsi, si vous avez l'annotation Column
dans le champ String de l'entité avec la longueur spécifiée et que la valeur réelle est supérieure à cette longueur, l'exception ci-dessus est levée.
Changer la classe du générateur:
<generator class="identity" />
à
<generator class="assigned" />
org.hibernate.AssertionFailure: null id dans l'entrée (ne pas vider la session après qu'une exception se soit produite)
Cela vient de nous arriver et je pensais ajouter quelques détails pour la postérité. Il s'avère que nous essayions de créer une entité avec un champ en double qui violait une condition:
Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'
Cette exception était cependant masquée car hibernate essayait de commit la session même si la création avait échoué. Lorsque la création a échoué, l'id n'a pas été défini, d'où l'erreur d'assert. Dans la trace de la pile, nous pouvions voir qu'Hibernate était en train de commettre:
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.Java:480)
Il aurait dû annuler la session et ne pas l’engager. Cela s'est avéré être un problème avec notre configuration de restauration. Nous utilisons les anciennes configurations XML et le chemin d’exception était incorrect:
<prop key="create*">PROPAGATION_REQUIRED,-org.x.y.LocalException</prop>
Le chemin LocalException
était incorrect et hibernate n'a pas généré d'erreur (ou il était enterré dans le journal de démarrage). Ce serait probablement aussi le cas si vous utilisez les annotations et ne spécifiez pas la ou les bonnes exceptions:
// NOTE: that the rollbackFor exception should match the throws (or be a subclass)
@Transactional(rollbackFor = LocalException.class)
public void create(Entity entity) throws AnotherException {
Une fois que nous avons corrigé notre câblage d'hibernation, nous avons correctement détecté l'exception "entrée en double" et la session a été correctement annulée et fermée.
Un problème supplémentaire à cela est que lorsque Hibernate lançait la variable AssertionFailure
, elle détenait un verrou de transaction dans MySQL qui devait ensuite être tué manuellement. Voir: https://stackoverflow.com/a/39397836/179850
Cela n'a rien à voir avec la requête en cours d'exécution. Cela déclenche simplement la couleur. À ce stade, Hibernate tente d'attribuer un identifiant à l'entité et semble avoir échoué pour une raison quelconque.
Pourriez-vous essayer de changer la classe du générateur:
<generator class="identity"/>
voyez si cela fait une différence. Assurez-vous également que la base de données que vous avez déployée dispose de la colonne d'incrémentation automatique correcte configurée sur la table?
Il semble que votre problème ressemble à celui-ci .
J'ai la même exception aussi, dans le fichier de configuration hibernate:
<property name="operateType" type="Java.lang.Integer">
<column name="operate_type" not-null="true" />
</property>
lorsque passe la valeur null à l'objet, exception se produit
"org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",
Je pense que la raison pour laquelle Hibernaye va vérifier la propriété 'not-null', alors, supprimer la propriété 'not-null' ou définir 'not-null' pour 'false' va résoudre le problème.
OK, j'ai continué mes recherches basées entre autres sur d'autres réponses de ce fil. Mais au bout du compte, nous étions devant un délai de production et je devais choisir la route d'urgence. Donc, au lieu de penser à l'hibernation, j'ai fait ces deux choses:
Suppression d'une bibliothèque jQuery que j'utilisais pour me concentrer sur l'un des formulaires. Je l’ai fait parce que j’avais lu quelque part que ce type de bogue pouvait survenir en raison de la publication d’une valeur NULL par un formulaire, ce qui entraînait l’identification NULL sur la ligne. Je soupçonnais que la bibliothèque jQuery ne fonctionnerait pas bien avec PrimeFaces et causerait des dysfonctionnements. Juste une intuition.
J'ai tué la relation mise en place par hibernate que j'avais entre utilisateur et adresse. (un seul requis, pas un à plusieurs) et a écrit le code moi-même en cas de besoin. Heureusement, cela n'a affecté qu'une page de manière significative, donc cela n'a pas demandé beaucoup de travail.
En bout de ligne: nous sommes entrés en ligne et l'application fonctionne depuis plusieurs jours sans erreur. Donc, cette solution peut ne pas être jolie - et je ne suis pas fière de moi -, mais j'ai une application en cours d'exécution et un client heureux.
J'ai eu la même erreur. Dans mon cas, c'était parce qu'avant cette exception, j'exécutais une requête create avec exception. L'exception est interceptée et n'annule pas la transaction dans le bloc catch. Ensuite, j'utilise cette transaction cassée dans une autre opération et après quelques temps, j'ai la même exception. Au début, je règle le mode flush sur manuel
public final Session getCurrentSession()
{
Session session = sessionFactory.getCurrentSession();
session.setFlushMode(FlushMode.MANUAL);
return session;
}
Ensuite, j'ai eu une autre exception, qui m'a expliqué ce qui s'est passé en fait. Ensuite, j'ai effectué l'annulation de transaction dans le bloc catch de ma méthode create. Et ça m'a aidé.
org.hibernate.AssertionFailure: null id dans l'entrée (ne vide pas la session après qu'une exception se soit produite)
Vous obtenez cette erreur lorsque vous utilisez la méthode de sauvegarde, si vous conservez l’historique des versions de l’activité de l’utilisateur et essayez de définir les valeurs suivantes setCreatedBy(1);
setModifiedBy(1);
setCreationDate();
setChangeDate();
} Vous obtiendrez l'erreur ci-dessus pour résoudre ce problème, vous devez créer les colonnes suivantes sur la table.
Created_By
Modified_By
Creation_Date
Change_Date
Si vous obtenez la même erreur en mettant à jour la méthode Update pour résoudre ce problème, il vous suffit de modifier la méthode Update () pour fusionner la méthode (). Cette J'espère vous avoir aidé.