Bonjour,
J'ai un problème lors de l'effacement d'un objet mappé avec Hibernate. Voici le schéma très simple de mon problème :
Code:
USER
+---------+----------+
| USER_ID | NAME |
+---------+----------+
| 1 | Pierre |
+---------+----------+
| 2 | Francois |
FUNCTION
+-------------+-----------+
| FUNCTION_ID | NAME |
+-------------+-----------+
| 5 | admin |
+-------------+-----------+
| 7 | ingenieur |
USER_FUNCTION
+---------+-------------+
| USER_ID | FUNCTION_ID |
+---------+-------------+
| 1 | 5 |
+---------+-------------+
| 1 | 7 |
+---------+-------------+
| 2 | 5 |
J'ai des
User (Utilisateur) et des
Function (Fonction).
- Un Utilisateur peut occuper plusieurs Fonctions.
- Une Fonction peut être attribuée à plusieurs Utilisateurs.
On est donc dans une
association N-N que j'ai mappé par un
set <many-to-many> (voir plus bas pour les fichiers de mapping).
Quand j'efface un
Utilisateur, les associations vers ses
Fonctions (table User_Function) sont bien retirées. Mais quand je tente d'effacer une
Fonction, je prends une Exception dans la tête.
Voici les détails d'implémentations :
Mappings Hibernate :User.hbm.xml :Code:
<hibernate-mapping>
<class name="beans.User" table="USER">
<id name="id" column="USER_ID">
<generator class="native" />
</id>
<property name="name" column="NAME" />
<set name="functions" table="USER_FUNCTION" sort="natural" lazy="false">
<key column="USER_ID" />
<many-to-many column="FUNCTION_ID" class="beans.Function" />
</set>
</class>
</hibernate-mapping>
Function.hbm.xml :Code:
<hibernate-mapping>
<class name="beans.Function" table="FUNCTION">
<id name="id" column="FUNCTION_ID">
<generator class="native" />
</id>
<property name="name" column="NAME" unique="true" />
<set name="users" table="USER_FUNCTION" inverse="true" lazy="false">
<key column="FUNCTION_ID" />
<many-to-many column="USER_ID" class="beans.User" />
</set>
</class>
</hibernate-mapping>
User.java :Code:
public class User {
private Long id;
private String name = "";
private SortedSet<Function> functions = new TreeSet<Function>();
...
}
Function.java :Code:
public class Function implements Comparable {
private Long id;
private String name;
private Set<User> users = new HashSet<User>();
...
}
Code pour supprimer une Fonction :Code:
public static void deleteFunction(long id) throws Exception {
Session session = factory.getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Function function = (Function) session.get(Function.class, id);
if (function != null)
session.delete(function);
else
throw new Exception("FunctionId not found");
tx.commit();
} catch (Exception e) {
if (tx != null)
tx.rollback();
throw e;
}
}
Sortie sur la console quand je tente de supprimer une Fonction :Code:
Hibernate: delete from FUNCTION where FUNCTION_ID=?
[WARN] (2007-05-04 17:49:32,265) org.hibernate.util.JDBCExceptionReporter - SQL Error: 1217, SQLState: 23000
[WARN] (2007-05-04 17:49:32,265) org.hibernate.util.JDBCExceptionReporter - SQL Error: 1217, SQLState: 23000
[ERROR] (2007-05-04 17:49:32,265) org.hibernate.util.JDBCExceptionReporter - Cannot delete or update a parent row: a foreign key constraint fails
[ERROR] (2007-05-04 17:49:32,265) org.hibernate.util.JDBCExceptionReporter - Cannot delete or update a parent row: a foreign key constraint fails
[ERROR] (2007-05-04 17:49:32,265) org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:249)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
at $Proxy0.flush(Unknown Source)
Sortie sur la console quand je tente de supprimer un Utilisateur :Code:
Hibernate: delete from USER_FUNCTION where USER_ID=?
Hibernate: delete from USER where USER_ID=?
---
Ce qui est bizarre, c'est qu'avec un Utilisateur, ça marche, mais pas avec une Fonction alors que le code est sur la même architecture. J'entends par là :
Code:
obj = session.get(...);
session.detele(obj);
Dans un cas, il arrive à comprendre qu'il faut s'attaquer d'abord à la table d'association (USER_FUNCTION), dans l'autre non. Pourtant j'ai bien préciser le
inverse="true" dans le fichier de mapping
Function.hbm.xml.
Je tente de faire quelque chose de simple, et j'avoue que je ne comprends pas vraiment pourquoi ça ne marche pas.
J'espère avoir été suffisamment précis dans l'exposé de mon problème. En vous remerciant d'avance,
piloupy
Hibernate version: 3.2.2