Bonjour,

J'utilise Hibernate pour des EJB3 avec la base de données Derby sur GlassFish V2UR1.
J'ai actuellement un problème ennuyeux. Ma base de données contient des alertes qui peuvent être consultées/modifiées continuellement.
Un EJB session s'occupe avec son entity manager de faire tous les accés à la base de données.

J'ai un problème de verrous sur des SELECT et je ne sais pas trop quoi faire ...

L'erreur est
[#|2008-04-16T11:11:28.973+0200|WARNING|sun-appserver9.1|org.hibernate.util.JDBCExceptionReporter|_ThreadID=81;_ThreadName=p: thread-pool-1; w: 64;_RequestID=0c72b586-ece1-43b2-9961-0a4f73992014;|SQL Error: -1, SQLState: 40001|#]

[#|2008-04-16T11:11:28.973+0200|SEVERE|sun-appserver9.1|org.hibernate.util.JDBCExceptionReporter|_ThreadID=81;_ThreadName=p: thread-pool-1; w: 64;_RequestID=0c72b586-ece1-43b2-9961-0a4f73992014;|Aucun verrou n'a pu être obtenu à cause d'un interblocage ; le cycle de verrous et d'unités en attente est :
Lock : ROW, ALERT, (1814,7)
Waiting XID : {175003, S} , APP, select distinct alert0_.USERID as col_0_0_ from Alert alert0_
Granted XID : {174982, X}
Lock : ROW, ALERT, (1815,6)
Waiting XID : {174982, S} , APP, select distinct alert0_.USERID as col_0_0_ from Alert alert0_
Granted XID : {175003, X}
. L'instruction SQL que le moteur de la base de données a choisi de supprimer est XID : 175003.|#]

[#|2008-04-16T11:11:28.988+0200|INFO|sun-appserver9.1|javax.enterprise.system.container.ejb|_ThreadID=81;_ThreadName=p: thread-pool-1; w: 64;UserAlert;|EJB5018: An exception was thrown during an ejb invocation on [UserAlert]|#]

[#|2008-04-16T11:11:28.988+0200|INFO|sun-appserver9.1|javax.enterprise.system.container.ejb|_ThreadID=81;_ThreadName=p: thread-pool-1; w: 64;|
javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean; nested exception is: javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: could not execute query
javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:641)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:73)
at com.monitor.ejb.alert.UserAlertBean.findAllUsers(UserAlertBean.java:66)
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:597)
at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1067)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:176) ....
at org.hibernate.loader.Loader.list(Loader.java:2023)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:393)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
... 28 more
Caused by: java.sql.SQLTransactionRollbackException: Aucun verrou n'a pu être obtenu à cause d'un interblocage ; le cycle de verrous et d'unités en attente est :Lock : ROW, ALERT, (1814,7)
Waiting XID : {175003, S} , APP, select distinct alert0_.USERID as col_0_0_ from Alert alert0_
Granted XID : {174982, X}
Lock : ROW, ALERT, (1815,6)
Waiting XID : {174982, S} , APP, select distinct alert0_.USERID as col_0_0_ from Alert alert0_
Granted XID : {175003, X}
. L'instruction SQL que le moteur de la base de données a choisi de supprimer est XID : 175003.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.PreparedStatement.executeQuery(Unknown Source)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:186)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1668)
at org.hibernate.loader.Loader.doQuery(Loader.java:662)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.doList(Loader.java:2144)
... 36 more

Les méthodes de mon session EJB qui appellent derby sont
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
/**
     * Find all user ID for current Alert.
     * @return a List of user ID
     */
    public Collection < String > findAllUsers() {
        List result = manager.createNamedQuery("findAllUsers").getResultList();
        manager.flush();
        return result;
    }
 
    /**
     * Remove an alert.
     * @param id the unique Alert's ID
     * @param flush boolean to define if must flush information
     * as we processed many items
     */
    public void removeAlert(Long id) {
        Alert alertToRemove = manager.find(Alert.class, id);        
        if (alertToRemove != null) {
            manager.remove(alertToRemove);
        }
        manager.flush();
    }
 
    /**
     * Find Alerts object for a given User ID.
     * @param userId the unique id
     * @return a collection of Alert object
     */
    public Collection < Alert > findAlertsForUser(String userId) {
        log.info("will extract info for : " + userId);
        Query query = manager.createNamedQuery("findByUserid")
            .setParameter("user", userId);
        List result = query.getResultList();
        manager.flush();
        return result;
    }
Les fichiers de config hibernate sont
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
<hibernate-mapping>
  <class name="com.monitor.ejb.alert.Alert" table="alert">
   <id name="id" type="long" column="ID" >
   <generator class="increment"/>
  </id>
  <property name="userid">
    <column name="USERID" sql-type="char(10)" not-null="true"/>
  </property>
  <property name="message">
     <column name="MESSAGE" sql-type="char(2000)" not-null="true"/>
  </property>
  </class>
</hibernate-mapping>
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
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
<session-factory>
      <property name="hibernate.connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
      <property name="hibernate.connection.url">jdbc:derby://127.0.0.1:1527/</property>
      <property name="hibernate.connection.username">admin</property>
      <property name="hibernate.connection.password">adminadmin</property>
      <property name="hibernate.connection.pool_size">10</property>
      <property name="show_sql">true</property>
      <property name="dialect">hibernate.dialect=org.hibernate.dialect.DerbyDialect</property>
      <property name="hibernate.hbm2ddl.auto">create</property>
      <!-- Mapping files -->
      <mapping resource="com.monitor.ejb.alert.Alert.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Que pourrais-je faire pour en finir avec ce blocage ...
Puis je changer quelque chose pour q'un select puisse accéder aux données sans verrou ?

Merci
Franck