org.hiberner.AssertionFailure: null id dans l'entrée (ne pas vider la Session après une exception se produit)
j'ai une application hibernate et JSF2 allant sur le serveur de déploiement et soudainement lancer une org.hiberner.AssertionFailure: null id in exception. Je vais fournir la trace de pile et le code immédiatement, mais voici quatre questions importantes d'abord:
-
cela se produit seulement sur le serveur de déploiement (Jboss & MySql tournant sur Windows Sever 2008.) Cela ne se produit pas sur ma machine de développement (Tomcat et MySql tournant sur Windoes 7 Pro) et pas non plus sur l'environnement de mise en scène (JBoss et MySql tournant sous Linux.)
-
en cherchant ceci, il semble que les gens obtiennent cette erreur en essayant d'insérer un objet. Mais j'obtiens l'erreur quand je fais une requête simple. (différentes requêtes différentes, en fait, comme l'erreur apparaît sur plusieurs pages au hasard.)
-
l'erreur ne se produit que de temps en temps. Si je fais un redémarrage de Jboss il disparaît, mais un temps retourne plus tard. En outre, il n'est pas cohérent, sur certains clics il est là, sur d'autres il n'est pas. Même quand il frappe, quand je fais un rafraîchissement simple de la page il retourne 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 d'adresse.
<?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 pleine 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)
13 réponses
L'exception:
org.hiberner.AssertionFailure: null id en entrée (ne pas rincer la Session après qu'une exception se produit)
nous dit que l'exception de session s'est produite avant le point où ce org.hibernate.AssertionFailure
est jeté.
pour être exact, le org.hibernate.AssertionFailure
est lancé quand le session.flush()
se produit, pas le point où l'erreur eu lieu.
ce qui précède est un fait, donc une conclusion possible de celui-ci est: quelque chose pourrait être supprimer l'exception originale.
donc, cherchez autre points d'erreur possibles: un save()
ou saveOrUpdate()
est peut-être essayer de persister une entité avec un null
champ où, dans le tableau, la colonne est NOT NULL
?
ASTUCE:
Pour aider au débogage, essayez d'ajouter un session.flush()
après chaque interaction avec l'objet Session
(par exemple session.save(obj)
, session.merge(obj)
, etc.), on espère que le org.hibernate.AssertionFailure
arrivera plus tôt, plus près de l'endroit où le vrai problème se produit. (Bien sûr, après le débogage, supprimer ces session.flush()
.)
Dans mon cas, le réel l'exception a eu lieu à l'intérieur d'un try/catch {}
bloc où le catch
supprimé l'exception (n'a pas rethrow ou me mettre en garde à ce sujet).
je parierais pour un problème de concurrence, mais il peut se produire à différents niveaux:
- une session d'hibernation peut être partagée entre différents utilisateurs si la session ouverte" classique "en vue" Modèle n'est pas correctement mis en œuvre
- une entité est partagée entre deux sessions utilisateur en raison de paramètres de cache d'hibernation
- une connexion JDBC est partagée entre deux différents session hibernate (moins probable)
mis à part ces sources potentielles de troubles, Je retirerais c3p0 (peut-être juste des rumeurs...) comme votre pile fournit déjà DataSource
avec la mise en commun des connexions intégrée avec le gestionnaire de transactions.
la @asdcjunior a répondu correctement. Il s'est passé quelque chose avant que l'exception ne soit jetée.
dans ce genre de situations (cela se produit souvent sur les tests d'intégration lorsque vous avez affaire à une seule transaction pour un test - par exemple @annotation de Transaction) j'invoque la méthode:
session.clear()
cela aide parce que tous les objets 'dirty' sont retirés de la session en cours donc quand le prochain flush est exécuté le problème ne apparaître.
exemple de flux:
- inscrire l'entité assignée (relation de plusieurs à plusieurs avec contrainte qui pourrait n'exister qu'une seule assignée)- > tout ok
- insérer la même entité d'affectation une fois de plus -> tout va bien, contrôleur dans ce cas retourner une sorte d'exception de mauvaise requête, sous le capot ressort jette L'IntegrityViolationException - > en test tout semble ok
- récupérez le dépôt et exécutez findAll ().size () pour vérifier le compte de existed assigned pour être sûr que nous n'avons qu'une seule tâche -> l'exception mentionnée est lancée ;/ qu'est-ce qui s'est passé? sur la session existe encore l'objet dirty, normalement la session serait détruite (erreur de retour du contrôleur) mais ici nous avons les assertions suivantes à vérifier concernant la base de données, donc la solution ici est session supplémentaire.clear () avant la prochaine db méthode liée exécutions
Exemple de débit correct:
- insérer l'entité assignée
- insérer la même entité de cession
- session.clair ()
- récupère le dépôt et exécute findAll().taille (en)
j'Espère que ça aide ;)
vous êtes probablement en train de frapper un insecte hiberné. (Je recommande de passer à au moins hibernation 3.3.2.GA.)
pendant ce temps, Hibernate fait mieux quand votre ID est nul pour que Hibernate puisse toujours faire la différence entre un nouvel objet qui n'a pas encore été persisté à la base de données et un qui est déjà dans la base de données. Changer le type de addressID
de long
à Long
permettra probablement de contourner le problème.
La trace de pile que vous avez fournie montre que vous voyez le problème sur une requête parce que votre requête force des Écritures tamponnées à être rincées à 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 à cette question J'ajoute juste essayer le bloc catch et dans le bloc catch j'ai écrit seesion.clair(); maintenant je peux continuer avec le reste des enregistrements à insérer dans la base de données
cordialement: Shahid Hussain Abbasi
cela n'a rien à voir avec la requête qui est exécutée. Cette juste déclenche la chasse d'eau. À ce stade, Hibernate est d'essayer d'attribuer un identifiant de l'entité et semble avoir échoué pour une raison quelconque.
pourriez-vous essayer de changer la classe de générateur:
<generator class="identity"/>
voyez si ça fait une différence. Avez-vous également fait en sorte que la base de données que vous avez déployée ait la colonne auto-incrementing correcte installée sur la table?
on dirait que votre numéro est similaire à celui-ci .
OK, j'ai continué la recherche basée entre autres sur d'autres réponses dans ce fil. Mais à la fin, comme nous étions confrontés à une date limite de production, j'ai dû choisir la déroute d'urgence. Donc, au lieu de comprendre l'hibernation, j'ai fait ces deux choses:
-
a enlevé une bibliothèque jQuery que j'utilisais pour me concentrer sur l'un des formulaires. J'ai fait cela parce que j'ai lu quelque part que ce type de bogue peut se produire en raison d'un formulaire affichant une valeur nulle -- provoquant l'id nul le long de la ligne. J'ai suspecté que la bibliothèque de jQuery ne soit pas bien assise avec les PrimeFaces, et cause une certaine forme de dysfonctionnement. Juste une intuition.
-
j'ai tué la relation que j'avais entre l'utilisateur et l'adresse. (un seul nécessaire, pas un à plusieurs) et a écrit le code moi-même lorsque nécessaire. Heureusement, cela n'a affecté qu'une page de manière significative, donc il n'y a pas eu beaucoup de travail.
La bas line: nous sommes allés en direct et l'application fonctionne depuis plusieurs jours sans aucune erreur. Donc cette solution n'est peut-être pas jolie -- et je ne suis pas fier de moi -- mais j'ai une application qui fonctionne et un client heureux.
changement de classe de la génératrice:
<generator class="identity" />
à
<generator class="assigned" />
org.hiberner.AssertionFailure: null id en entrée (ne pas rincer la Session après qu'une exception se produit)
cela nous est arrivé et j'ai pensé ajouter quelques détails pour la postérité. Il s'avère que nous essayions de créer une entité avec un champ dupliqué qui violait une condition:
Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry '' for key
'Index_schools_name'
cette exception était cependant masquée parce que hibernate essayait de commit la session même si la création a échoué. Lorsque le créé pas alors l'id n'a pas été définie d'où l'assertion d'erreur. Dans la pile, nous avons pu voir que hibernate commettait:
at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit
(HibernateTransactionManager.java:480)
cela aurait dû faire reculer la session, pas l'engager. Cela s'est avéré être un problème avec notre configuration de retour. 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 hiberné n'a pas lancé d'erreur (ou il a été enterré dans le spew de journal de démarrage). Ce serait probablement aussi le cas si vous utilisez les annotations et ne spécifiez pas la(les) Bonne (s) exception (s):
// 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 réparé notre câblage d'hibernation, nous avons vu correctement l'exception de "duplicate entry" et la session était correctement tournée et fermée.
une autre ride de ceci était que lorsque hibernate lançait le AssertionFailure
, il tenait un verrou de transaction dans MySQL qui a ensuite dû être tué à la main. Voir: https://stackoverflow.com/a/39397836/179850
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>
quand passer la valeur null à l'objet, se produire exception
"org.hibernate.AssertionFailure: null id in com.idex.auctions.model.Address entry",
je pense que la raison pour laquelle Hibernaye vérifiera la propriété 'not-null', donc, supprimer la propriété 'not-null' ou Définir 'not-null' pour 'false', résoudra le problème.
cela se produit parfois lorsque la longueur de la chaîne est supérieure à celle permise par DB.
DataIntegrityViolationException
se traduit par cette exception qui est un comportement étrange par hibernation.
donc si vous avez Column
annotation sur le champ String de l'entité avec la longueur spécifiée et la valeur réelle est plus grande que cette longueur, l'exception ci-dessus est lancée.
org.hiberner.AssertionFailure: null id en entrée (ne pas rincer la Session après qu'une exception se produit)
vous obtenez cette erreur en utilisant la méthode save, si vous maintenez l'historique de version de l'activité de l'utilisateur et essayer 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 lors de la mise à jour méthode pour résoudre ce problème juste vous devez changer la méthode Update() pour fusionner () la méthode qu'il
j'espère que vous avez aidé.