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 :
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
Voici le mapping d'un lieu.
Note : Un lieu peut avoir un lieu supérieur (ou pas si c'est le niveau maximum)
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>
La modification fonctionne correctement lorsque qu'il y a un lieu parent mais pas lorsqu'il n'y en a pas.

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 :
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')}" />
--> l'input correspondant au champ lieu.cpteLieuParent.lieId n'est pas renseigné.

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 :
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();
J'ai donc l'erreur lors du commit :
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
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.

Faut-il donc avant la mise à jour rajouter le code suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
if(lieu.getCpteLieuParent() != null and lieu.getCpteLieuParent().getLieId==0)
setCpteLieuParent=null
ou y-a-t-il autre chose de plus propre? en jsp ou en "hibernate"

Cordialement