IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JPA Java Discussion :

Problème de transaction - JPA manager par Spring


Sujet :

JPA Java

  1. #1
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut Problème de transaction - JPA manager par Spring
    Bonjour,

    J'ai un soucis de transaction. J'essaie de faire un insert d'un objet sur un champ unique, et si le champ unique existe déjà je voudrais retenter l'insert avec un incrément. C'est le moyen le plus rapide je pense (vu la quantité d'insert que je dois faire et vu qu'il y a très peu de cas où il faudra retenter l'insert).

    Donc pour cela lors de mon merge de mon DAO j'ai catché l'erreur par EntityExistException que je remonte par une Exception perso à mon service. Cela fonctionne bien et me permet de retenter l'insert avec l'incrément. Mais le problème est qu'un rollback est exécuté quand même et une exception de transaction est lancée. Voici l'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Exception in thread "main" org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:465)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
    	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
    	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    	at $Proxy63.findValidLogin(Unknown Source)
    	at org.esco.sarapis.db.domain.gestion.impl.InsertManagerImpl.main(InsertManagerImpl.java:92)
    Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly
    	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:51)
    	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)
    	... 8 more
    et les LOG pour retracer l'opération :
    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
    13391 DEBUG  [main] AbstractBeanFactory           - Returning cached instance of singleton bean 'loginAliasManagerImpl'
    13406 DEBUG  [main] AbstractBeanFactory           - Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
    13406 DEBUG  [main] AbstractPlatformTransactionManager     - Using transaction object [org.springframework.orm.jpa.JpaTransactionManager$JpaTransactionObject@14fa79d]
    13406 DEBUG  [main] AbstractPlatformTransactionManager     - Creating new transaction with name [org.esco.sarapis.db.domain.gestion.ILoginAliasManager.findValidLogin]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
    13422 DEBUG  [main] JpaTransactionManager         - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@eb840f] for JPA transaction
    13485 DEBUG  [main] SessionImpl                   - opened session at timestamp: 12174115935
    13485 DEBUG  [main] JDBCTransaction               - begin
    13485 DEBUG  [main] ConnectionManager             - opening JDBC connection
    13485 DEBUG  [main] DriverManagerDataSource       - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/JSarapis]
    13500 DEBUG  [main] JDBCTransaction               - current autocommit status: true
    13500 DEBUG  [main] JDBCTransaction               - disabling autocommit
    13500 DEBUG  [main] JDBCContext                   - after transaction begin
    13516 DEBUG  [main] JpaTransactionManager         - Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle: com.mysql.jdbc.Connection@1b80d9b]
    13516 DEBUG  [main] TransactionSynchronizationManager     - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@856d3b] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@1c5ddc9] to thread [main]
    13531 DEBUG  [main] TransactionSynchronizationManager     - Bound value [org.springframework.orm.jpa.EntityManagerHolder@3e1d25] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@1eb717e] to thread [main]
    13531 DEBUG  [main] TransactionSynchronizationManager     - Initializing transaction synchronization
    13531 DEBUG  [main] TransactionAspectSupport      - Getting transaction for [org.esco.sarapis.db.domain.gestion.ILoginAliasManager.findValidLogin]
    13531 INFO   [main] LoginAliasManagerImpl         - Create new Login : aaaaa
    13531 INFO   [main] LoginAliasManagerImpl         - Try to insert Login
    13531 DEBUG  [main] GenericDaoImpl                - Merging org.esco.sarapis.db.entity.personne.Login instance
    13547 DEBUG  [main] TransactionSynchronizationManager     - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@3e1d25] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@1eb717e] bound to thread [main]
    13547 DEBUG  [main] IdentifierValue               - id unsaved-value: 0
    13547 DEBUG  [main] AbstractSaveEventListener     - transient instance of: org.esco.sarapis.db.entity.personne.Login
    13547 DEBUG  [main] DefaultMergeEventListener     - merging transient instance
    13563 DEBUG  [main] AbstractSaveEventListener     - saving [org.esco.sarapis.db.entity.personne.Login#<null>]
    13563 DEBUG  [main] AbstractSaveEventListener     - executing insertions
    13563 DEBUG  [main] AbstractSaveEventListener     - executing identity-insert immediately
    13563 DEBUG  [main] AbstractEntityPersister       - Inserting entity: org.esco.sarapis.db.entity.personne.Login (native id)
    13578 DEBUG  [main] AbstractBatcher               - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    13578 DEBUG  [main] AbstractBatcher               - insert into Login (nom) values (?)
    Hibernate: insert into Login (nom) values (?)
    13578 DEBUG  [main] AbstractBatcher               - preparing statement
    13594 DEBUG  [main] AbstractEntityPersister       - Dehydrating entity: [org.esco.sarapis.db.entity.personne.Login#<null>]
    13594 DEBUG  [main] NullableType                  - binding 'aaaaa' to parameter: 1
    13594 DEBUG  [main] AbstractBatcher               - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    13594 DEBUG  [main] AbstractBatcher               - closing statement
    13594 DEBUG  [main] JDBCExceptionReporter         - could not insert: [org.esco.sarapis.db.entity.personne.Login] [insert into Login (nom) values (?)]
    com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry 'aaaaa' for key 2
    	...
     
    13594 WARN   [main] JDBCExceptionReporter         - SQL Error: 1062, SQLState: 23000
    13594 ERROR  [main] JDBCExceptionReporter         - Duplicate entry 'aaaaa' for key 2
    13594 DEBUG  [main] AbstractEntityManagerImpl     - mark transaction for rollback
    13594 ERROR  [main] GenericDaoImpl                - Merge failed - Entity already exists : 
    13594 DEBUG  [main] GenericDaoImpl                - ====>>> duplicate entry.
    13594 DEBUG  [main] LoginAliasManagerImpl         - Interception de l'erreur : null
    13594 INFO   [main] LoginAliasManagerImpl         - Create new Login : aaaaa0
    13594 INFO   [main] LoginAliasManagerImpl         - Try to insert Login
    13594 DEBUG  [main] GenericDaoImpl                - Merging org.esco.sarapis.db.entity.personne.Login instance
    13594 DEBUG  [main] TransactionSynchronizationManager     - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@3e1d25] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@1eb717e] bound to thread [main]
    13594 DEBUG  [main] IdentifierValue               - id unsaved-value: 0
    13594 DEBUG  [main] AbstractSaveEventListener     - transient instance of: org.esco.sarapis.db.entity.personne.Login
    13594 DEBUG  [main] DefaultMergeEventListener     - merging transient instance
    13610 DEBUG  [main] AbstractSaveEventListener     - saving [org.esco.sarapis.db.entity.personne.Login#<null>]
    13610 DEBUG  [main] AbstractSaveEventListener     - executing insertions
    13610 DEBUG  [main] AbstractSaveEventListener     - executing identity-insert immediately
    13610 DEBUG  [main] AbstractEntityPersister       - Inserting entity: org.esco.sarapis.db.entity.personne.Login (native id)
    13610 DEBUG  [main] AbstractBatcher               - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    13610 DEBUG  [main] AbstractBatcher               - insert into Login (nom) values (?)
    Hibernate: insert into Login (nom) values (?)
    13610 DEBUG  [main] AbstractBatcher               - preparing statement
    13610 DEBUG  [main] AbstractEntityPersister       - Dehydrating entity: [org.esco.sarapis.db.entity.personne.Login#<null>]
    13610 DEBUG  [main] NullableType                  - binding 'aaaaa0' to parameter: 1
    13610 DEBUG  [main] IdentifierGeneratorFactory     - Natively generated identity: 13
    13610 DEBUG  [main] AbstractBatcher               - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    13610 DEBUG  [main] AbstractBatcher               - closing statement
    13610 DEBUG  [main] GenericDaoImpl                - Merge successful.
    13610 INFO   [main] LoginAliasManagerImpl         - insert OK
    13610 DEBUG  [main] TransactionAspectSupport      - Completing transaction for [org.esco.sarapis.db.domain.gestion.ILoginAliasManager.findValidLogin]
    13610 DEBUG  [main] AbstractPlatformTransactionManager     - Triggering beforeCommit synchronization
    13610 DEBUG  [main] AbstractPlatformTransactionManager     - Triggering beforeCompletion synchronization
    13610 DEBUG  [main] AbstractPlatformTransactionManager     - Initiating transaction commit
    13610 DEBUG  [main] JpaTransactionManager         - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@eb840f]
    13610 DEBUG  [main] JDBCTransaction               - rollback
    13688 DEBUG  [main] JDBCTransaction               - re-enabling autocommit
    13688 DEBUG  [main] JDBCTransaction               - rolled back JDBC Connection
    13688 DEBUG  [main] JDBCContext                   - after transaction completion
    13688 DEBUG  [main] ConnectionManager             - aggressively releasing JDBC connection
    13688 DEBUG  [main] ConnectionManager             - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    13688 DEBUG  [main] SessionImpl                   - after transaction completion
    13688 DEBUG  [main] AbstractPlatformTransactionManager     - Triggering afterCompletion synchronization
    13688 DEBUG  [main] TransactionSynchronizationManager     - Clearing transaction synchronization
    13688 DEBUG  [main] TransactionSynchronizationManager     - Removed value [org.springframework.orm.jpa.EntityManagerHolder@3e1d25] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@1eb717e] from thread [main]
    13688 DEBUG  [main] TransactionSynchronizationManager     - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@856d3b] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@1c5ddc9] from thread [main]
    13688 DEBUG  [main] JpaTransactionManager         - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@eb840f] after transaction
    13688 DEBUG  [main] EntityManagerFactoryUtils     - Closing JPA EntityManager
    13703 DEBUG  [main] SessionImpl                   - closing session
    13703 DEBUG  [main] ConnectionManager             - connection already null in cleanup : no action
    voici mes différents codes :

    Le dao générique :
    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
    public abstract class GenericDaoImpl<T> implements IGenericDao<T> {
     
    	/** Logger. */
    	static final Logger LOGGER = Logger.getLogger(GenericDaoImpl.class);
     
    	/** Type de l'entity. */
    	private Class<T> entityBeanType;
     
    	/** Le persistence contexte injecté par Spring. */
    	@PersistenceContext(type = PersistenceContextType.TRANSACTION) 
    	private EntityManager entityManager;
     
    	// Constructeurs
    	/**
             * Constructeur de l'objet GenericJpaDao.java.
             * @param classe Type de l'entity actuel.
             */
    	public GenericDaoImpl(final Class<T> classe) {
    		this.entityBeanType = classe;
    	}
     
    public T merge(final T entity) throws DuplicateEntryException {
    		LOGGER.debug("Merging " + this.entityBeanType.getName() + " instance");		
    		T res = null;
            try {
                res = entityManager.merge(entity);
                LOGGER.debug("Merge successful.");
            } catch (EntityExistsException e) {
                LOGGER.error("Merge failed - Entity already exists : " 
                        /*+ e.getMessage()*/);
               // if (e.getMessage().contains("Duplicate entry")) {
                    LOGGER.debug("====>>> duplicate entry.");
                    throw new DuplicateEntryException(/*e.getMessage()*/);
               // }
               // LOGGER.debug("====<> duplicate entry passe à côté.");
                //throw e;
            } catch (NestableRuntimeException e) {
                // TODO: handle exception
                LOGGER.error("Merge de " + getEntityBeanType().getName() + " Impossible. " 
                        + e.getMessage(), e);
                throw new DatabaseException("Merge impossible", e);
            }
            return res;
    	}
    le dao étendu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Repository
    public class LoginDaoImpl extends GenericDaoImpl<Login> implements ILoginDao {
     
        /**
         * Constructeur de l'objet LoginDaoImpl.java.
         */
        public LoginDaoImpl() {
            super(Login.class);
            // TODO Auto-generated constructor stub
        }
     
    }
    et le 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
    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
    @Service
    @Scope("singleton")
    public class LoginAliasManagerImpl implements ILoginAliasManager {
     
        private static final Logger LOGGER = Logger.getLogger(LoginAliasManagerImpl.class);
     
     
        @Resource
        private ILoginDao loginDao;
     
        public LoginAliasManagerImpl() {
            // TODO Auto-generated constructor stub
        }
     
     
        @Transactional
        private Login findLogin(final String possibleValue, final int i) {
            Login login = null;
            try {                
                if (i == -1) {
                    LOGGER.info("Create new Login : " + possibleValue);
                    login = new Login(possibleValue);
                } else {
                    LOGGER.info("Create new Login : " + possibleValue + i);
                    login = new Login(possibleValue + i);
                }
                LOGGER.info("Try to insert Login");
                login = loginDao.merge(login);
                LOGGER.info("insert OK");
            } catch (DuplicateEntryException e) {
                // TODO Auto-generated catch block
                // e.printStackTrace();
                LOGGER.debug("Interception de l'erreur : " + e.getMessage());
     
                return null;
            }
     
            return login;
        }
     
     
        @Transactional
        public Login findValidLogin(final String possibleValue) {
            Login login = null;
            int i = -1;
            while (login == null) {
                login = findLogin(possibleValue, i);
                i++;
            }
            return login;
        }
    }
    et ma config Spring :
    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
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
     
    	<!-- Propriétés à chager -->
    	<bean name="propertyPlaceholder"
    		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="locations">
    			<value>classpath:db.properties</value>
    		</property>
    	</bean>
     
    	<!-- Source de donnéees DB -->
    	<bean id="dataSource"
    		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    		p:driverClassName="${db.driver}" p:url="${db.url}"
    		p:username="${db.username}" p:password="${db.password}" />
     
    	<!-- Configuration de l'unité de persistence -->
    	<bean id="persistenceUnitManager"
    		class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    		<!-- On spécifie ici les lieux où trouver les fichiers de persistence -->
    		<property name="persistenceXmlLocations">
    			<list>
    				<value>classpath*:META-INF/persistence.xml</value>
    			</list>
    		</property>
    		<!-- On spécifie ici les sources de données à utiliser, locale ou distante -->
    		<property name="dataSources">
    			<map>
    				<entry key="localDataSource" value-ref="dataSource" />
    				<!--<entry key="remoteDataSource" value-ref="remote-db" />-->
    			</map>
    		</property>
    		<!-- On spécifie ici la sources de données par défaut si aucune source de données n'est disponible -->
    		<property name="defaultDataSource" ref="dataSource" />
    	</bean>
     
    	<!-- Configuration du manager d'entity -->
    	<bean id="entityManagerFactory"
    		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    		p:dataSource-ref="dataSource"
    		p:persistenceUnitManager-ref="persistenceUnitManager">
    		<!-- On spécifie ici l'adaptateur Spring pour l''implémentation JPA utilisée -->
    		<property name="jpaVendorAdapter">
    			<bean
    				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    				p:databasePlatform="${db.dialect}" p:database="${db.database}"
    				p:showSql="true" p:generate-ddl="true" />
    		</property>
    		<!-- On spécifie ici le tisseur utilisée pour la modification du ByteCode, cf documentation de Spring pour plus de précisions -->
    		<property name="loadTimeWeaver">
    			<bean
    				class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    		</property>
    		<!-- On spécifie ici le dialecte utilisé en fonction de l'implémentation JPA utilisée -->
    		<property name="jpaDialect">
    			<bean
    				class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    		</property>
    	</bean>
     
    	<!-- le gestionnaire de transactions -->
    	<bean id="transactionManager"
    		class="org.springframework.orm.jpa.JpaTransactionManager"
    		p:entityManagerFactory-ref="entityManagerFactory"
    		scope="prototype">
    		<property name="jpaDialect">
    			<bean
    				class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    		</property>
    	</bean>
     
    	<tx:annotation-driven transaction-manager="transactionManager"/>
     
    	<!--Activation de la prise en compte des annotations de type @Required,@Autowired,@PostConstruct,
    		@PreDestroy,@Resource,@PersistenceContext,@PersistenceUnit -->
    	<context:annotation-config />
     
    	<context:component-scan base-package="org.esco.sarapis.db" />
     
     
    	<!-- traduction des exceptions -->
    	<bean
    		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
     
    	<!-- persistence -->
    	<bean
    		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
     
     
    </beans>
    Quelqu'un aurait une idée de comment résoudre cela ?

    Sinon j'envisageai de recréer une transaction lors d'un Duplicate entry, mais le problème est que je ne vois pas comment je pourrais réinitialiser la transaction.

  2. #2
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Sinon j'ai réussi à gérer ce problème en passant en mode non managé par Spring... C'est à dire que je manage moi même l'injection de mon entityManager et que je gère mes transactions...

    Mais j'aimerai effectuer cela en restant en mode managé. Quelqu'un aurait une idée ?

    Sinon quelle serait la meilleur façon de gérer l'ensemble ? Car cela n'est qu'une infime partie de ce que je dois faire... Dois-je reste (pour ce qui est réalisé) en mode manager et juste pour cette partie passer en mode non managé, ou dois-je tout passer en mode non managé ?

    J'avoue que mon manque d'expérience ne me permet pas d'avoir une idée claire sur cela...

    Et mon gros problème est de gérer justement les exceptions d'insertion dans la base de donnée si je reste en mode managé...

  3. #3
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Après identification de mon problème voici ce que je dois faire :

    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
    @Service
    @Scope("singleton")
    public class LoginAliasManagerImpl implements ILoginAliasManager {
     
        private static final Logger LOGGER = Logger.getLogger(LoginAliasManagerImpl.class);
     
        @Resource
        private ILoginDao loginDao;
     
        public LoginAliasManagerImpl() {
            // TODO Auto-generated constructor stub
        }
     
        @Transactional
        public Login findLogin(final String possibleValue, final int i) {
            Login login = null;
            try {             
                if (i == -1) {
                    LOGGER.info("Create new Login : " + possibleValue);
                    login = new Login(possibleValue);
                } else {
                    LOGGER.info("Create new Login : " + possibleValue + i);
                    login = new Login(possibleValue + i);
                }
                LOGGER.info("Try to insert Login");
                login = loginDao.merge(login);
                LOGGER.info("insert OK");
            } catch (org.springframework.dao.DataIntegrityViolationException e) {
                LOGGER.debug("Interception de l'erreur : " + e.getMessage());
                return null;
            }
     
            return login;
        }
     
       public Login findValidLogin(final String possibleValue) {
            Login login = null;
            int i = -1;
            while (login == null) {
            login = findLogin(possibleValue, i);
              i++;
            }
            return login;
        }
    }
    Donc à partir de cela voici les choix que j'ai :

    Now you have no transactions at all.

    For transactions to work you need proxies and proxies are not invoked if you call the method from the same class. You can:

    a) split your class in 2, so that transactional method will be invoked through the proxy
    b) use transactiontemplate instead of proxies
    c) use aspectj weaving instead of proxies



    Quelqu'un pourrait m'aider car là j'ai testé la solution a) mais ça ne marche pas, j'arrive seulement à persisté en mettant l'annotation @transactional dans mon DAO, ce qui n'est vraiment pas top ...

    et on me redirige ici : http://static.springframework.org/sp...-prog-template
    pour la b)

    Sinon pour le reste comment puis-je faire ?

  4. #4
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Bon et bien c'est résolu

    En utilisant le TransactionTemplate voici ce que j'ai modifié (si ça peut aider d'autres personnes)

    le service gérant la transaction.
    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
    @Service
    @Scope("singleton")
    public class LoginAliasManagerImpl implements ILoginAliasManager {
     
        protected static final Logger LOGGER = Logger.getLogger(LoginAliasManagerImpl.class);
     
        @Resource 
        private ILoginDao loginDao;
     
        private TransactionTemplate transactionTemplate;
     
        public LoginAliasManagerImpl() {
            super();
        }
     
        private Login findLogin(final String possibleValue, final int i) {
            Login login = null;
            if (i == -1) {
                LOGGER.info("Create new Login : " + possibleValue);
                login = new Login(possibleValue);
            } else {
                LOGGER.info("Create new Login : " + possibleValue + i);
                login = new Login(possibleValue + i);
            }
            LOGGER.info("Try to insert Login");
            final Login flogin = login;
            login =  (Login) transactionTemplate.execute(new TransactionCallback() {
                public Object doInTransaction(final TransactionStatus status) {
                    try {
                        return loginDao.merge(flogin);
                    } catch (org.springframework.dao.DataIntegrityViolationException e) {
                        LOGGER.debug("Interception de l'erreur : " + e.getMessage());
                        status.setRollbackOnly();
                        return null;
                    }
                }
     
            });
            LOGGER.info("insert OK");
            return login;
        }
     
        public Login findValidLogin(final String possibleValue) {
            Login login = null;
            int i = -1;
            while (login == null) {
                login =  findLogin(possibleValue, i);
                i++;
            }
            return login;
        }
     
        public TransactionTemplate getTransactionTemplate() {
            return this.transactionTemplate;
        }
     
        public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
            this.transactionTemplate = transactionTemplate;
        }
     
    }
    et le fichier de config Spring :
    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
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    	<bean name="propertyPlaceholder"		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="locations">
    			<value>classpath:db.properties</value>
    		</property>
    	</bean>
    
    	<bean id="dataSource"		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    		p:driverClassName="${db.driver}" p:url="${db.url}"
    		p:username="${db.username}" p:password="${db.password}" />
    
    	<bean id="persistenceUnitManager"
    		class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    		<property name="persistenceXmlLocations">
    			<list>				<value>classpath*:META-INF/varPersistence.xml</value>
    			</list>
    		</property>
    		
    		<property name="dataSources">
    			<map>
    				<entry key="localDataSource" value-ref="dataSource" />
    			</map>
    		</property>
    		<property name="defaultDataSource" ref="dataSource" />
    	</bean>
    
    	<bean id="entityManagerFactory"		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    		p:dataSource-ref="dataSource"
    		p:persistenceUnitManager-ref="persistenceUnitManager">
    		<property name="jpaVendorAdapter">
    			<bean				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    				p:databasePlatform="${db.dialect}" p:database="${db.database}"
    				p:showSql="true" p:generate-ddl="true" />
    		</property>
    		<property name="loadTimeWeaver">
    			<bean				class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    		</property>
    		<property name="jpaDialect">
    			<bean				class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    		</property>
    	</bean>
    
    	<bean id="transactionManager"
    		class="org.springframework.orm.jpa.JpaTransactionManager"
    		p:entityManagerFactory-ref="entityManagerFactory">
    		<property name="jpaDialect">
    			<bean				class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    		</property>
    	</bean>
    
    	<tx:annotation-driven transaction-manager="transactionManager" />
    
    	<context:annotation-config />
    
    	<context:component-scan base-package="org.esco.sarapis.db" />
    
    	<bean		class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    	<bean		class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
    
    <bean id="sharedTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
       <property name="timeout" value="30" />
       <property name="transactionManager" ref="transactionManager" />
    </bean>
    
    <bean id="serviceLoginAliasManager" class="org.esco.sarapis.db.domain.gestion.impl.LoginAliasManagerImpl">
       <property name="transactionTemplate" ref="sharedTransactionTemplate" />
    </bean>

  5. #5
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    En fait il vaut mieux oublier cela le mieux est de passer par une autre transaction avec une propagation à REQUIRES_NEW...

    Mais le problème est que si on veut récupérer l'objet persisté et managé on obtient qu'un detached object... Car la nouvelle transaction une fois fermée supprime le managment...

    Quelqu'un aurait une solution avec le EntityManager et sans Template ?

  6. #6
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Pour ceux qui sont intéressé, il semblerait que le tout fonctionne très bien avec l'entitymanager en EXTENDED et en injectant l'entityManager suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <bean id="entityManager"
    		class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
    	</bean>

  7. #7
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Un nouveau retour...

    L'entityManager en EXTENDED est à oublier pour des requêtes en masses car cela peut provoquer des

    optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)


    Sinon quelqu'un aurait une idée sur comment passer en mode étendu cela m'interesse

  8. #8
    Membre averti
    Inscrit en
    Mars 2004
    Messages
    56
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 56
    Par défaut
    Bon il semblerait qu'il faille configurer le transaction_isolation de mysql... Quelqu'un aurait une idée sur le level d'isolation que je devrais mettre ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Data] JPA managé par Spring 2.5 - transaction
    Par nean_j dans le forum Spring
    Réponses: 9
    Dernier message: 25/02/2011, 13h58
  2. JPA manager par Spring - configuration
    Par nean_j dans le forum JPA
    Réponses: 1
    Dernier message: 17/09/2008, 16h05
  3. JPA manager par Spring - Pagination
    Par nean_j dans le forum JPA
    Réponses: 1
    Dernier message: 08/09/2008, 12h07
  4. Réponses: 2
    Dernier message: 11/07/2008, 14h44
  5. [Data] [Spring DAO][JPA] JPA managé par Spring 2.5
    Par Ylias dans le forum Spring
    Réponses: 2
    Dernier message: 09/06/2008, 19h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo