Bonjour,
j'ai un service de création d'utilisateurs, dont je me sert pour tester la gestion des transactions avec Spring et JDBC en utilisant un TransactionTemplate. Pourtant, si je déclenche une exception en créant 2 fois le même utilisateur, et que je mets le status de la transaction à rollbackOnly, les utilisateurs créés précédemment dans la même transaction sont toujours là !
Voici un extrait du code de mon service :
Un extrait de UserDao :
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 private TransactionTemplate txTemplate; private IUserDao userDao; public UserService(IUserDao dao, PlatformTransactionManager txManager) { this.userDao = dao; txTemplate = new TransactionTemplate(txManager); } public User testTransaction( ) { txTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); User user = null; user = txTemplate.execute(new TransactionCallback<User>( ) { @Override public User doInTransaction(TransactionStatus status) { User user = null; try { createUser("étienne", "789456"); createUser("marcel", "123456"); user = createUser("étienne", "789456"); } catch (DataAccessException e) { status.setRollbackOnly( ); if ( !status.isNewTransaction( )) throw e; } return user; } }); return user; } public User createUser(final String login, final String password) { txTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_SERIALIZABLE); txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); return txTemplate.execute(new TransactionCallback<User>( ) { @Override public User doInTransaction(TransactionStatus status) { String hashPassword = BCrypt.hashpw(password, BCrypt.gensalt( )); User user = null; try { userDao.createUser(login, hashPassword); } catch (DataAccessException e) { status.setRollbackOnly( ); if ( !status.isNewTransaction( )) throw e; } return user; } }); }
Voici mon fichier de configuration pour l'injection des beans :
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 private NamedParameterJdbcTemplate template; public void setDatasource(DataSource datasource) { template = new NamedParameterJdbcTemplate(datasource); } public User createUser(String login, String hashPassword) { MapSqlParameterSource params = new MapSqlParameterSource( ); params.addValue("login", login); params.addValue("hashPassword", hashPassword); template.update(createUserQuery, params); return new User(login, hashPassword); }
Et enfin le code de mon test unitaire :
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 <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="username" value="xx"/> <property name="password" value="yy"/> <property name="url" value="jdbc:mysql://localhost/gesicoba"/> <property name="defaultAutoCommit" value="false"/> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource"/> </bean> <bean id="userDao" class="fr.atatorus.gesicoba.dao.UserDao" init-method="init"> <property name="datasource" ref="datasource"/> <property name="queryLoader" ref="queryLoader"/> </bean> <bean id="userService" class="fr.atatorus.gesicoba.services.UserService"> <constructor-arg ref="userDao"/> <constructor-arg ref="txManager"/> </bean>
Puisque je crée 2 fois étienne, j'obtiens bien une exception, dans laquelle je mets bien le status de la transaction à rollbackOnly. Pourtant quand je regarde dans ma base, étienne existe bien, le rollback n'a pas eu lieu...
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 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( { "../test-application-context.xml" }) public class UserServiceTest { @Resource private IUserService userService; @Test public void testTransaction( ) { User user = userService.testTransaction( ); assertNull(user); user = userService.connectUser("étienne", "789456"); assertNull(user); } .... }
Un grand merci à ceux qui me donneront la source du mystère !!
Edit : j'ai fini par trouver. Le problème ne venait pas de mon code, mais de mySql. Je n'avais pas précisé à la création le moteur à utiliser, et ma table était de type MyIsam. En indiquant que je voulais un moteur InnoDB, ça fonctionne.
Partager