8
votes

Impossible de gérer des exceptions hibernées à l'intérieur des méthodes @TransAderal dans l'application Spring

J'ai une question. J'utilise le printemps + hibernate et je ne peux pas gérer des exceptions dans des méthodes marquées comme @Transactional forte>. Auparavant, quand j'ai utilisé Spring JDBC, tout a fonctionné, tout va bien. de
de
Les classes DAO sont marquées avec @RePository.
Voici Snipper de mon ancien code.
en service: strong>
xxx pré>


à DAO: strong> de
P>

2013-10-21 14:51:17 ERROR BookingController:89 - Unhandled exception
org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into booking (ticket_id, user_id, booking_id) values (?, ?, ?)]; constraint ["CONSTRAINT_INDEX_2 ON PUBLIC.BOOKING(TICKET_ID) VALUES ( /* key:1 */ 2, 1, 1)"; SQL statement:
insert into booking (ticket_id, user_id, booking_id) values (?, ?, ?) [23505-173]]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at cdp.tarasenko.springmvc.task3.service.TicketsService$$EnhancerByCGLIB$$fabdc899.bookTickets(<generated>)
    at cdp.tarasenko.springmvc.task3.controller.BookingController.bookTickets(BookingController.java:54)
    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 org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:594)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
    at org.eclipse.jetty.server.Server.handle(Server.java:351)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:857)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:609)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
    ... 51 more
Caused by: org.h2.jdbc.JdbcBatchUpdateException: Нарушение уникального индекса или первичного ключа: "CONSTRAINT_INDEX_2 ON PUBLIC.BOOKING(TICKET_ID) VALUES ( /* key:1 */ 2, 1, 1)"
Unique index or primary key violation: "CONSTRAINT_INDEX_2 ON PUBLIC.BOOKING(TICKET_ID) VALUES ( /* key:1 */ 2, 1, 1)"; SQL statement:
insert into booking (ticket_id, user_id, booking_id) values (?, ?, ?) [23505-173]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1167)
    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
    ... 59 more


7 commentaires

Veuillez poster la trace de la pile de l'exception qui est lancée.


Est-ce vraiment important? Le point principal est que je ne peux pas gérer des exceptions que j'ai besoin. Mais j'ai mis à jour mon message avec l'exemple d'exception lorsque l'application essaie d'insérer une valeur qui enfreint une colonne unique.


Essayez d'ajouter un enfin sur le try-attraper dans la méthode de service. Ce qui se produit?


@Sotirios Delimanolis, je vais essayer. Mais ce comportement a l'air assez étrange que pour moi.


@Sotirios Delimanolis code dans le bloc final exécute. Cependant, code dans le bloc de capture - non. On dirait que Hibernate Transaction Manager jette une exception seulement après (à) les méthodes de transaction (et la transaction en cours). Avez-vous des idées comment le faire lancer une exception à l'intérieur de la méthode?


La seule chose à laquelle je puisse penser, c'est que des trucs sont en train de faire paresseusement. Que l'appel à bookingDao.bookticket ne lance pas une exception . L'exception est lancée dans le transactionmanager , qui se produit dans le proxy qui enveloppe votre classe @service . Si tel est vrai, c'est un design vraiment médiocre de leur part imo.


J'ai eu le même type de problème, j'ai retourné-le aux transactions manuelles, à la session.getTransaction () type de choses à l'intérieur du DAO


3 Réponses :


2
votes

Jetez un coup d'œil à hibernate flushmode

défaut hiberanaetemplate flushmode est flusmode.auto , la synchronisation de la session se produira sur commit ou avant que des requêtes pour empêcher l'état avancé.

Vous pouvez modifier le mode de rinçage HibernateTeTemplate sur flushmode.always, inefficace et non recommandé (mais fonctionnera comme vous vous attendez maintenant), ou appelez Session.flush () à certains points.

voir hiberanatetemplate.setflushMode () et session.flush ()


0 commentaires

1
votes

Vous n'obtenez pas les exceptions de DB comme des violations de contraintes avant d'avoir commis la TX et TX s'engage dans le gestionnaire de transactions. La meilleure solution serait la manipulation des exceptions de Gestionnaire TX à l'aide d'un aspect de l'après-variateur (AOP). Vous pouvez également appeler vos méthodes @TransActional à l'intérieur d'une autre méthode non transactionnelle dans votre service et de saisir les exceptions. Personnellement, je n'aime pas le plus tard, car vous devrez créer une méthode d'emballage pour tous vos services.


3 commentaires

J'ai pensé à une deuxième approche, mais je n'aime pas aussi. Je vais essayer une approche d'AOP. Merci.


Les exceptions de responsable de l'entité attrapant pourraient être un peu difficiles. Je l'ai fait avant, mais ne vous souvenez pas comment pour le moment.;) Faites-moi savoir si vous avez des problèmes, je peux le trouver pour vous.


L'affranchissement de l'AOP n'est pas appelé à l'exception du TXMGR. Mon contrôleur est également annoté par "@scope (proxymode = scopedproxymode.target_class)" que je devais insérer pour que l'annotation transactionnelle ait un effet. J'ai également essayé avec l'annotation de la commande (la plus haute et la plus basse), à ​​la fois sur le contrôleur et / ou sur ma classe AOP. J'ai trouvé aucun moyen de forcer le Spring AOP pour attraper également des exceptions à partir de la gestion de la TRX.



1
votes

ou vous pouvez appeler votre code transactionnel en mode transaction explicite.

E.g. xxx


0 commentaires