Bonjour,

J'ai remarqué un problème très gênant pouvant conduire à une corruption de ma base de donnée:

Dans mon projet utilisant Hibernate et les EJB3, je possède un entity de type "Expression" qui est rattaché à un entity "Operator" qui est abstrait.
Et enfin les "Operator" sont hérité en "Function", "OperatorLogic"...

Voici le diagramme UML simplifié correspondant:


Le problème que j'ai trouvé est le suivant:

Si j'essaye de supprimer une "Function" qui est lié à une expression, en utilisant la méthode remove de l'entity manager, il me sort une exception de type EJBTransactionRolledbackException "ConstraintViolationException" ce qui est tout-à-fait normal.
Ce qui l'est moins, c'est que, bien que la fonction soit utilisé, il affiche toujours le message, mais supprime quand même la ligne de ma table "function" sans supprimer la ligne de la table "operator" qui porte le même id...

En regardant le log sql, c'est comme-si hibernate avait committé la transaction juste après avoir supprimé la ligne de la table function ou alors c'est comme si la base de donnée était en mode auto-commit.


Résultat:

Si j'essaye de faire un expression.getOperator(), il me sort l'exception:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
Error performing load command
org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: OperatorEntite
Et je me retrouve avec une base corrompu. La corruption provient bien du fait qu'il y a des lignes dans la table "operator" dont les ID n'apparaissent dans aucunes des tables hérités.

Hormis ce problème toutes les transactions fonctionnent correctement.

Pour gérer les transactions j'utilise sur les méthodes de ma façade l'anotation:
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
Hibernate a pourtant bien effectué un rollback, sinon l'exception retournée n'aurait pas été une EJBTransactionRolledbackException.

Ce problème semble se produire avec toutes les versions 3 d'Hibernate.

J'utilise une base de donnée PostreSQL 8.2.


Merci davance.


Voici les entity que j'utilise:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
public class Expression extends Base{
 
	private Operator operator;
 
	@ManyToOne
	public Operator getOperator() {
		return operator;
	}
	public void setOperator(Operator operator) {
		this.operator = operator;
	}
}
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
@Entity
public abstract class Operator extends Base{
 
	private Collection<Expression> expression;
 
	public Operator() {
		super();
	}
 
	@OneToMany(mappedBy="operator")
	public Collection<Expression> getExpression() {
		return expression;
	}
	public void setExpression(Collection<Expression> expression) {
		this.expression = expression;
	}
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
@Entity
public class Function extends Operator{
 
	public Function() {
		super();
	}	
}

Voici la trace lors de la relecture de l'objet qui est sensé ne pas avoir été supprimé:

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
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
11:18:16,277 INFO  [event.def.DefaultLoadEventListener] Error performing load command
org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: ejb.dao.operator.OperatorEntite
	at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:101)
	at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:123)
	at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:374)
	at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3634)
	at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1302)
	at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1291)
	at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1323)
	at org.hibernate.loader.Loader.getRow(Loader.java:1230)
	at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)
	at org.hibernate.loader.Loader.doQuery(Loader.java:724)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
	at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3072)
	at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
	at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:873)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:590)
	at org.hibernate.type.EntityType.resolve(EntityType.java:412)
	at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:877)
	at org.hibernate.loader.Loader.doQuery(Loader.java:752)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
	at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3072)
	at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
	at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:873)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:590)
	at org.hibernate.type.EntityType.resolve(EntityType.java:412)
	at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:877)
	at org.hibernate.loader.Loader.doQuery(Loader.java:752)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.doList(Loader.java:2228)
	at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2157)
	at org.hibernate.loader.Loader.list(Loader.java:2117)
	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
	at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
	at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
	at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
	at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
	...
11:18:16,294 INFO  [event.def.DefaultLoadEventListener] Error performing load command
org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: OperatorEntite
	at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:101)
	at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:123)
	at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:374)
	at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3634)
	at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1302)
	at org.hibernate.impl.SessionImpl.instantiate(SessionImpl.java:1291)
	at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1323)
	at org.hibernate.loader.Loader.getRow(Loader.java:1230)
	at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:603)
	at org.hibernate.loader.Loader.doQuery(Loader.java:724)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
	at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3072)
	at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
	at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:873)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:590)
	at org.hibernate.type.EntityType.resolve(EntityType.java:412)
	at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:877)
	at org.hibernate.loader.Loader.doQuery(Loader.java:752)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
	at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
	at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3072)
	at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
	at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:873)
	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:590)
	at org.hibernate.type.EntityType.resolve(EntityType.java:412)
	at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
	at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:877)
	at org.hibernate.loader.Loader.doQuery(Loader.java:752)
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
	at org.hibernate.loader.Loader.doList(Loader.java:2228)
	at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2157)
	at org.hibernate.loader.Loader.list(Loader.java:2117)
	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
	at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
	at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
	at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
	at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
	...

Les requêtes exécutées par Hibernate sont:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
11:55:00,096 INFO  [STDOUT] Hibernate: 
    delete 
    from
        Function 
    where
        id=?
11:55:00,105 INFO  [STDOUT] Hibernate: 
    delete 
    from
        Operator 
    where
        id=?