Bonjour,

Je suis en cours d'écrire d'un socle DAO plus robuste pour mon appli et je suis dans la phase de gestion des transactions.
Je reprends fiérement ma gestion de transaction de ma première appli, que j'avais mis pas mal de temps à configurer et me rend compte que finalement que tout fonctionne mais que des commits sont faits à la fin de chaque accès en base.
Pire que chaque accès à ma base postgres est en ExclusiveLock.
Je repars donc d'une feuille blanche.

J'ai donc créer un nouveau projet avec Spring Starter Project, et cocher la case JPA.
Ensuite création d'une entité toute simple Person avec les annotations @Entity, @Id, etc...
Une interface héritant de CrudRepository. La config :

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
 
@EnableJpaRepositories(basePackages = { "demo.repositories" })
@EnableAutoConfiguration
@ComponentScan(basePackages = { "demo" })
@EntityScan(basePackages = { "demo.entities" })
@EnableTransactionManagement
public class Config {
 
	@Bean
	public DataSource dataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("org.h2.Driver");
		dataSource.setUrl("jdbc:h2:mem:datajpa");
		dataSource.setUsername("sa");
		dataSource.setPassword("");
		return dataSource;
	}
 
	@Bean
	public JpaVendorAdapter jpaVendorAdapter() {
		HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
		hibernateJpaVendorAdapter.setShowSql(true);
		hibernateJpaVendorAdapter.setGenerateDdl(false);
		hibernateJpaVendorAdapter.setDatabase(Database.H2);
		return hibernateJpaVendorAdapter;
	}
Le main :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
 
ConfigurableApplicationContext context = SpringApplication.run(Config.class, args);
PersonService service = context.getBean(PersonService.class);
Person person = new Person();
person.setNom("TEST");
person.setPrenom("Toto);
service.save(person);
 
Iterable<Person> persons = service.findAll();
System.out.println(persons.iterator().hasNext());
la classe de service :
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
 
@Service
@Transactional(readOnly = true)
public class PersonService {
 
	@Autowired
	private PersonRepository personRepository;
 
	public List<Person> findAll() {
		return Lists.newArrayList(personRepository.findAll());
	}
 
	public Person save(Person person) {
		return personRepository.save(person);
	}
 
}
J'ai même posé un @Transactional(readOnly = true) sur l'interface PersonRepository.
Et pourtant le save fonctionne et j'ai toujours mon commit qui passe lors du findAll().

Extrait du log pour le create (Spring en debug)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
2014-11-17 10:27:15.939 [main] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl org.hibernate.engine.transaction.spi.AbstractTransactionImpl-begin:160 - begin 
2014-11-17 10:27:15.939 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-obtainConnection:226 - Obtaining JDBC connection 
2014-11-17 10:27:15.939 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-obtainConnection:232 - Obtained JDBC connection 
2014-11-17 10:27:15.939 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doBegin:69 - initial autocommit status: true 
2014-11-17 10:27:15.939 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doBegin:71 - disabling autocommit 
2014-11-17 10:27:16.090 [main] DEBUG org.hibernate.engine.spi.ActionQueue org.hibernate.engine.spi.ActionQueue-addResolvedEntityInsertAction:194 - Executing identity-insert immediately 
2014-11-17 10:27:16.100 [main] DEBUG org.hibernate.SQL org.hibernate.engine.jdbc.spi.SqlStatementLogger-logStatement:109 - insert into person (id, nom, prenom) values (null, ?, ?) 
2014-11-17 10:27:16.120 [main] DEBUG org.hibernate.id.IdentifierGeneratorHelper org.hibernate.id.IdentifierGeneratorHelper-getGeneratedIdentity:94 - Natively generated identity: 1 
2014-11-17 10:27:16.140 [main] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl org.hibernate.engine.transaction.spi.AbstractTransactionImpl-commit:175 - committing 
2014-11-17 10:27:16.140 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doCommit:113 - committed JDBC Connection 
2014-11-17 10:27:16.140 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-releaseManagedConnection:126 - re-enabling autocommit 
2014-11-17 10:27:16.150 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-releaseConnection:246 - Releasing JDBC connection 
2014-11-17 10:27:16.150 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-releaseConnection:264 - Released JDBC connection
Log pour le findAll
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
 
2014-11-17 10:27:25.714 [main] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl org.hibernate.engine.transaction.spi.AbstractTransactionImpl-begin:160 - begin 
2014-11-17 10:27:25.724 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-obtainConnection:226 - Obtaining JDBC connection 
2014-11-17 10:27:25.724 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-obtainConnection:232 - Obtained JDBC connection 
2014-11-17 10:27:25.724 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doBegin:69 - initial autocommit status: true 
2014-11-17 10:27:25.734 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doBegin:71 - disabling autocommit 
2014-11-17 10:27:25.805 [main] DEBUG org.hibernate.jpa.criteria.CriteriaQueryImpl org.hibernate.jpa.criteria.CriteriaQueryImpl-interpret:327 - Rendered criteria query -> select generatedAlias0 from Person as generatedAlias0 
2014-11-17 10:27:25.945 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl org.hibernate.hql.internal.ast.QueryTranslatorImpl-parse:294 - parse() - HQL: select generatedAlias0 from demo.entities.Person as generatedAlias0 
2014-11-17 10:27:25.975 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl org.hibernate.hql.internal.ast.QueryTranslatorImpl-showHqlAst:312 - --- HQL AST ---
 \-[QUERY] Node: 'query'
    \-[SELECT_FROM] Node: 'SELECT_FROM'
       +-[FROM] Node: 'from'
       |  \-[RANGE] Node: 'RANGE'
       |     +-[DOT] Node: '.'
       |     |  +-[DOT] Node: '.'
       |     |  |  +-[IDENT] Node: 'demo'
       |     |  |  \-[IDENT] Node: 'entities'
       |     |  \-[IDENT] Node: 'Person'
       |     \-[ALIAS] Node: 'generatedAlias0'
       \-[SELECT] Node: 'select'
          \-[IDENT] Node: 'generatedAlias0'
 
2014-11-17 10:27:25.975 [main] DEBUG org.hibernate.hql.internal.ast.ErrorCounter org.hibernate.hql.internal.ast.ErrorCounter-throwQueryException:113 - throwQueryException() : no errors 
2014-11-17 10:27:26.025 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker org.hibernate.hql.internal.antlr.HqlSqlBaseWalker-beforeStatement:121 - select << begin [level=1, statement=select] 
2014-11-17 10:27:26.085 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromElement org.hibernate.hql.internal.ast.tree.FromElement-doInitialize:158 - FromClause{level=1} : demo.entities.Person (generatedAlias0) -> person0_ 
2014-11-17 10:27:26.085 [main] DEBUG org.hibernate.hql.internal.ast.tree.FromReferenceNode org.hibernate.hql.internal.ast.tree.FromReferenceNode-setResolved:77 - Resolved : generatedAlias0 -> person0_.id 
2014-11-17 10:27:26.085 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker org.hibernate.hql.internal.antlr.HqlSqlBaseWalker-beforeStatementCompletion:125 - select : finishing up [level=1, statement=select] 
2014-11-17 10:27:26.085 [main] DEBUG org.hibernate.hql.internal.ast.HqlSqlWalker org.hibernate.hql.internal.ast.HqlSqlWalker-processQuery:665 - processQuery() :  ( SELECT ( {select clause} person0_.id ) ( FromClause{level=1} person person0_ ) ) 
2014-11-17 10:27:26.105 [main] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor org.hibernate.hql.internal.ast.util.JoinProcessor-addJoinNodes:187 - Using FROM fragment [person person0_] 
2014-11-17 10:27:26.115 [main] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker org.hibernate.hql.internal.antlr.HqlSqlBaseWalker-afterStatementCompletion:129 - select >> end [level=1, statement=select] 
2014-11-17 10:27:26.115 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl org.hibernate.hql.internal.ast.QueryTranslatorImpl-analyze:281 - --- SQL AST ---
 \-[SELECT] QueryNode: 'SELECT'  querySpaces (person)
    +-[SELECT_CLAUSE] SelectClause: '{select clause}'
    |  +-[ALIAS_REF] IdentNode: 'person0_.id as id1_0_' {alias=generatedAlias0, className=demo.entities.Person, tableAlias=person0_}
    |  \-[SQL_TOKEN] SqlFragment: 'person0_.nom as nom2_0_, person0_.prenom as prenom3_0_'
    \-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[generatedAlias0], fromElementByTableAlias=[person0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
       \-[FROM_FRAGMENT] FromElement: 'person person0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=generatedAlias0,role=null,tableName=person,tableAlias=person0_,origin=null,columns={,className=demo.entities.Person}}
 
2014-11-17 10:27:26.115 [main] DEBUG org.hibernate.hql.internal.ast.ErrorCounter org.hibernate.hql.internal.ast.ErrorCounter-throwQueryException:113 - throwQueryException() : no errors 
2014-11-17 10:27:26.125 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl org.hibernate.hql.internal.ast.QueryTranslatorImpl-generate:263 - HQL: select generatedAlias0 from demo.entities.Person as generatedAlias0 
2014-11-17 10:27:26.125 [main] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl org.hibernate.hql.internal.ast.QueryTranslatorImpl-generate:264 - SQL: select person0_.id as id1_0_, person0_.nom as nom2_0_, person0_.prenom as prenom3_0_ from person person0_ 
2014-11-17 10:27:26.135 [main] DEBUG org.hibernate.hql.internal.ast.ErrorCounter org.hibernate.hql.internal.ast.ErrorCounter-throwQueryException:113 - throwQueryException() : no errors 
2014-11-17 10:27:26.185 [main] DEBUG org.hibernate.SQL org.hibernate.engine.jdbc.spi.SqlStatementLogger-logStatement:109 - select person0_.id as id1_0_, person0_.nom as nom2_0_, person0_.prenom as prenom3_0_ from person person0_ 
2014-11-17 10:27:26.185 [main] DEBUG org.hibernate.loader.Loader org.hibernate.loader.Loader-processResultSet:952 - Result set row: 0 
2014-11-17 10:27:26.195 [main] DEBUG org.hibernate.loader.Loader org.hibernate.loader.Loader-getRow:1486 - Result row: EntityKey[demo.entities.Person#1] 
2014-11-17 10:27:26.205 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad org.hibernate.engine.internal.TwoPhaseLoad-doInitializeEntity:160 - Resolving associations for [demo.entities.Person#1] 
2014-11-17 10:27:26.205 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad org.hibernate.engine.internal.TwoPhaseLoad-doInitializeEntity:286 - Done materializing entity [demo.entities.Person#1] 
2014-11-17 10:27:26.235 [main] DEBUG org.hibernate.engine.transaction.spi.AbstractTransactionImpl org.hibernate.engine.transaction.spi.AbstractTransactionImpl-commit:175 - committing 
2014-11-17 10:27:26.235 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-doCommit:113 - committed JDBC Connection 
2014-11-17 10:27:26.235 [main] DEBUG org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction-releaseManagedConnection:126 - re-enabling autocommit 
2014-11-17 10:27:26.245 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-releaseConnection:246 - Releasing JDBC connection 
2014-11-17 10:27:26.245 [main] DEBUG org.hibernate.engine.jdbc.internal.LogicalConnectionImpl org.hibernate.engine.jdbc.internal.LogicalConnectionImpl-releaseConnection:264 - Released JDBC connection
Initialement j'avais tout paramétré en XML. J'ai ici fait le choix de l'annotation pour être plus rapide.
D'avance merci de votre aide.

HadanMarv