{"id":3047,"date":"2014-03-15T02:04:15","date_gmt":"2014-03-15T02:04:15","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/15\/can-not-handle-hibernate-exceptions-inside-transactional-methods-in-spring-app-collection-of-common-programming-errors\/"},"modified":"2014-03-15T02:04:15","modified_gmt":"2014-03-15T02:04:15","slug":"can-not-handle-hibernate-exceptions-inside-transactional-methods-in-spring-app-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/15\/can-not-handle-hibernate-exceptions-inside-transactional-methods-in-spring-app-collection-of-common-programming-errors\/","title":{"rendered":"Can not handle hibernate exceptions inside @Transactional methods in Spring app-Collection of common programming errors"},"content":{"rendered":"<p>I have a question. I use Spring+Hibernate and I can&#8217;t handle exceptions in methods marked as <strong>@Transactional<\/strong>. Previously, when I used Spring JDBC everything worked just fine. DAO classes are marked with @Repository. Here is snipper of my old code.<\/p>\n<p><strong>in service:<\/strong><\/p>\n<p><\/p>\n<pre><code>@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})\n        public boolean bookTickets(Integer userId, List ticketsId) throws TicketsServiceException {\n            Integer currId = null;\n            try {\n                for (Integer ticketId : ticketsId) {\n                    currId = ticketId;\n                    Ticket ticket = ticketDAO.getTicketById(ticketId);\n                    bookingDAO.bookTicket(ticket, userId);\n                }\n            } catch (DuplicateKeyException e) {\n                throw new TicketsServiceException(String.format(MESSAGE_TICKET_ALREADY_BOOKED, currId));\n            } catch (EmptyResultDataAccessException e) {\n            throw new TicketsServiceException(String.format(MESSAGE_NO_SUCH_TICKET, currId));\n            }\n            return true;   \n<\/code><\/pre>\n<p>\n<strong>in dao:<\/strong><\/p>\n<pre><code>@Transactional(propagation = Propagation.MANDATORY)\npublic void bookTicket(Ticket ticket, final int userId) {\n    MapSqlParameterSource map = new MapSqlParameterSource();\n    map.addValue(Constants.TABLE_BOOKING.FIELD_TICKET_ID, ticket.getId());\n    map.addValue(Constants.TABLE_BOOKING.FIELD_USER_ID, userId);\n\n    int rowsAffected = template.update(QUERY_INSERT_BOOKING, map);\n    if (LOG.isTraceEnabled()) {\n        LOG.trace(\"Affected \" + rowsAffected + \" rows.\");\n    }\n}\n<\/code><\/pre>\n<p>Now I&#8217;m moving my DAO from Spring JDBC onto hibernate 3. That&#8217;s what I have now.<br \/>\n<strong>in service:<\/strong><\/p>\n<pre><code>@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class})\npublic boolean bookTickets(Integer userId, List ticketsId) throws TicketsServiceException {\n    Integer currId = null;\n    try {\n        for (Integer ticketId : ticketsId) {\n            currId = ticketId;\n            Ticket ticket = ticketDAO.getTicketById(ticketId);\n            bookingDAO.bookTicket(new Booking(ticketId, userId));\n        }\n    } catch (Exception e) {\n        throw new TicketsServiceException(String.format(MESSAGE_THERE_IS_NO_SUCH_TICKET_OR_ALREADY_BOOKED, currId));\n    }\n    return true;\n}\n<\/code><\/pre>\n<p><strong>in dao:<\/strong><\/p>\n<pre><code>@Override\npublic void bookTicket(Booking booking) {\n    getHibernateTemplate().save(booking);\n}\n<\/code><\/pre>\n<p>The problem is that I can&#8217;t handle exceptions inside try-catch block in service method. They are throwing directly into my controller.<\/p>\n<p>I think the problem is in difference between transaction managers <em>org.springframework.jdbc.datasource.DataSourceTransactionManager<\/em> in Spring JDBC and <em>org.springframework.orm.hibernate3.HibernateTransactionManager<\/em> in hibernate, but I dont have any ideas how to overcome this problem, so I need your help.<\/p>\n<p><strong>AFTER UPDATE. ADDED EXAMPLE OF EXCEPTION.<\/strong><\/p>\n<pre><code>2013-10-21 14:51:17 ERROR BookingController:89 - Unhandled exception\norg.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:\ninsert into booking (ticket_id, user_id, booking_id) values (?, ?, ?) [23505-173]]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update\n    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)\n    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793)\n    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)\n    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)\n    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)\n    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)\n    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)\n    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)\n    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)\n    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)\n    at cdp.tarasenko.springmvc.task3.service.TicketsService$$EnhancerByCGLIB$$fabdc899.bookTickets()\n    at cdp.tarasenko.springmvc.task3.controller.BookingController.bookTickets(BookingController.java:54)\n    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n    at java.lang.reflect.Method.invoke(Method.java:597)\n    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)\n    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)\n    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)\n    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)\n    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)\n    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)\n    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)\n    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)\n    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)\n    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)\n    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)\n    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)\n    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)\n    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:594)\n    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)\n    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)\n    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)\n    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:233)\n    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)\n    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)\n    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)\n    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)\n    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)\n    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)\n    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)\n    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)\n    at org.eclipse.jetty.server.Server.handle(Server.java:351)\n    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)\n    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:900)\n    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:954)\n    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:857)\n    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)\n    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)\n    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:609)\n    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45)\n    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)\n    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)\n    at java.lang.Thread.run(Thread.java:662)\nCaused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update\n    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)\n    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)\n    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)\n    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)\n    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)\n    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)\n    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)\n    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)\n    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)\n    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)\n    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)\n    ... 51 more\nCaused by: org.h2.jdbc.JdbcBatchUpdateException: ????????? ??????????? ??????? ??? ?????????? ?????: \"CONSTRAINT_INDEX_2 ON PUBLIC.BOOKING(TICKET_ID) VALUES ( \/* key:1 *\/ 2, 1, 1)\"\nUnique index or primary key violation: \"CONSTRAINT_INDEX_2 ON PUBLIC.BOOKING(TICKET_ID) VALUES ( \/* key:1 *\/ 2, 1, 1)\"; SQL statement:\ninsert into booking (ticket_id, user_id, booking_id) values (?, ?, ?) [23505-173]\n    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1167)\n    at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)\n    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)\n    ... 59 more\n<\/code><\/pre>\n<p>Is there any ways to handle exceptions inside service layer?<br \/>\nThank you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have a question. I use Spring+Hibernate and I can&#8217;t handle exceptions in methods marked as @Transactional. Previously, when I used Spring JDBC everything worked just fine. DAO classes are marked with @Repository. Here is snipper of my old code. in service: @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = {Exception.class}) public boolean bookTickets(Integer userId, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3047","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/3047","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=3047"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/3047\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=3047"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=3047"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=3047"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}