Bonjour.
J'ai un problème lors de la mise à jour d'un objet via Hibernate suite à la saisie dans un formulaire.
Je pense avoir vu comment résoudre le problème, mais je voulais savoir si c'était la bonne méthode.
Voici l'erreur :
Voici le mapping d'un lieu.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 2014-03-13 10:34:43,659 DEBUG cpte.dao.CpteLieuDao - update(T) : cpte.hibernate.CpteLieu Hibernate: update CPTEADM.CPTE_LIEU set LIE_ID_PARENT=?, LIE_LIBELLE=?, LIE_CODE=?, LIE_CENTRE_PROFIT=?, LIE_NIVEAU=? where LIE_ID=? 2014-03-13 10:34:52,167 ERROR cpte.pages.admin.lieu.PageLieuAction - org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cpte.hibernate.CpteLieu
Note : Un lieu peut avoir un lieu supérieur (ou pas si c'est le niveau maximum)
La modification fonctionne correctement lorsque qu'il y a un lieu parent mais pas lorsqu'il n'y en a pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 <hibernate-mapping> <class name="cpte.hibernate.CpteLieu" table="CPTE_LIEU"> <id name="lieId" type="long"> <column name="LIE_ID" precision="22" scale="0" /> <generator class="increment" /> </id> <many-to-one name="cpteLieuParent" class="cpte.hibernate.CpteLieu" fetch="select"> <column name="LIE_ID_PARENT" precision="22" scale="0" /> </many-to-one> <property name="lieLibelle" type="string"> <column name="LIE_LIBELLE" length="80" /> </property> ... <set name="cpteLieux" table="CPTE_LIEU" order-by="LIE_ID" inverse="true" lazy="true" fetch="select"> <key> <column name="LIE_ID_PARENT" precision="22" scale="0" /> </key> <one-to-many class="cpte.hibernate.CpteLieu" /> </set> </class> </hibernate-mapping>
Dans le java, avant d'arriver sur le formulaire, le lieu contient les paramètre suivants : "cpteLieuParent=null"
J'arrive donc sur mon formulaire jsp de modification :
--> l'input correspondant au champ lieu.cpteLieuParent.lieId n'est pas renseigné.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 <s:form name="lieuForm"> <s:textfield name="lieu.lieId" readonly="true" label="%{getText('label.lieu.lieId')}" /> <s:textfield name="lieu.lieLibelle" required="true" label="%{getText('label.lieu.lieLibelle')}" /> .... <s:textfield name="lieu.cpteLieuParent.lieId" label="%{getText('label.lieu.lieIdParent')}" />
Lors de la validation du formulaire, j'arrive donc dans le java, qui considère que le champ cpteLieuParent est non null et contient un id cpteLieuParent.lieId=0.
Lors de la mise à jour :
J'ai donc l'erreur lors du commit :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 HibernateUtil.currentSession().beginTransaction(); CpteLieuDao.getInstance().update(lieu); HibernateUtil.currentSession().getTransaction().commit();Pour cela vient du fait que le commit ne fonctionne pas car en base de donnée, il n'y a pas de lieu avec l'id=0.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Hibernate: update CPTEADM.CPTE_LIEU set LIE_ID_PARENT=?, LIE_LIBELLE=?, LIE_CODE=?, LIE_CENTRE_PROFIT=?, LIE_NIVEAU=? where LIE_ID=? 2014-03-13 10:34:52,167 ERROR cpte.pages.admin.lieu.PageLieuAction - org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cpte.hibernate.CpteLieu
Faut-il donc avant la mise à jour rajouter le code suivant :
ou y-a-t-il autre chose de plus propre? en jsp ou en "hibernate"
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 if(lieu.getCpteLieuParent() != null and lieu.getCpteLieuParent().getLieId==0) setCpteLieuParent=null
Cordialement
Partager