Bonjour,
je developpe une webapp avec spring pour ma partie DAO (sur une base Oracle 9) et je viens d'identifier un problème très gênant. D'abord, voici la config de mes objets d'accès DAO:
pour résumer, mon DataSource est un BasicDataSource de apache commons. il est directement injecté dans mon JdbcTemplate par Spring, qui est à son tour injecté dans deux classes DbReader et DbWriter, qui servent donc à lire et à écrire dans la base. A noter que dans toute l'appli je me sers toujours de ces deux objets pour lire et écrire dans la base de données. Enfin on voit un proxy sur ces deux classes qui sert à intercepter et à logger les exceptions lors de l'accès à la base de données.
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 <!-- ********** LowLevel Database Hitting ********** --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@server.fr.net.intra:1521:BOSFRDI2"/> <property name="username" value="user"/> <property name="password" value="password"/> <property name="maxActive" value="4"/> <property name="maxIdle" value="4"/> <property name="maxWait" value="5000"/> <property name="removeAbandoned" value="true"/> <property name="removeAbandonedTimeout" value="5000"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"><ref bean="dataSource"/></property> </bean> <!-- ********** HighLevel Database Hitting and Log AOP ********** --> <bean id="dbWriterTarget" class="ubix.dbAccess.DbWriterImpl"> <property name="jdbcTemplate"><ref bean="jdbcTemplate"/></property> </bean> <bean id="dbErrorLogger" class="ubix.dbAccess.DbErrorLogger"/> <bean id="dbWriter" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>ubix.dbAccess.DbWriter</value> </property> <property name="interceptorNames"> <list> <value>dbErrorLogger</value> </list> </property> <property name="target"> <ref bean="dbWriterTarget"/> </property> </bean> <bean id="dbReaderTarget" class="ubix.dbAccess.DbReaderImpl"> <property name="jdbcTemplate"><ref bean="jdbcTemplate"/></property> <property name="dbCache"><ref local="dbCache"/></property> </bean> <bean id="dbReader" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>ubix.dbAccess.DbReader</value> </property> <property name="interceptorNames"> <list> <value>dbErrorLogger</value> </list> </property> <property name="target"> <ref bean="dbReaderTarget"/> </property> </bean>
En fait, en utilisation normale, tout ce passe bien, l'appli crée et détruit ses connections correctement. Je suis l'évolutions de ces dernières avec la vue v$session pour ceux qui connaissent oracle.
Quand une erreur sql se produit, et donc que Dbreader ou Dbwriter renvoie une RuntimeException (provenant du JdbcTemplate), le proxy l'intercepte et la logge, mais les connections ouvertes par mon JdbcTemplate pour la ou les requêtes en cause ne semble pas être fermées. Du coup le nombre de sessions ouvertes sur la base augmente avec le temps et on finit par atteindre le maximum autorisé sur la base, ce qui bloque toute l'appli (et toute les autres qui utilisent la base aussi, tant qu'à faire).
Quelqu'un saurait ce qu'il faut que je fasse pour fermer ses connections en cas d'erreur Oracle? Je n'ai pas trouvé dans les méthodes du jdbcTemplate de moyen de fermer la connexion en cours.
N'hésitez pas à me demander du code supplémentaire au besoin. Je précise que je ne suis pas un super expert de Java, et que c'est ma première appli dans ce langage, donc n'hésitez pas non plus à pointer mes erreurs de conception.
Merci d'avance.
Partager