{"id":1254,"date":"2022-09-17T20:40:12","date_gmt":"2023-11-18T11:52:47","guid":{"rendered":"https:\/\/www.silicloud.com\/blog\/uncategorized\/an-illustration-of-spring-transaction-management-using-jdbc\/"},"modified":"2024-03-18T15:08:28","modified_gmt":"2024-03-18T15:08:28","slug":"an-illustration-of-spring-transaction-management-using-jdbc","status":"publish","type":"post","link":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/","title":{"rendered":"An illustration of Spring Transaction Management using JDBC."},"content":{"rendered":"<p>One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is an essential responsibility in any enterprise application. Previously, we learned to handle transactions using the JDBC API. However, Spring offers comprehensive assistance for transaction management, allowing developers to concentrate on their business logic and alleviate concerns about data integrity during system failures.<\/p>\n<h2>Managing transactions in the Spring framework<\/h2>\n<p>There are several advantages of employing Spring Transaction Management:<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>Declarative Transaction Management is supported by Spring where AOP is used to ensure data integrity in most cases.<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>\n<li style=\"list-style-type: none;\">\n<ol>Most transaction APIs such as JDBC, Hibernate, JPA, JDO, JTA etc. are supported. We simply need to use the appropriate transaction manager implementation class. For instance, org.springframework.jdbc.datasource.DriverManagerDataSource for JDBC transaction management or org.springframework.orm.hibernate3.HibernateTransactionManager for Hibernate as the ORM tool.<\/ol>\n<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<ol>Programmatic transaction management is also supported by using TransactionTemplate or a PlatformTransactionManager implementation.<\/ol>\n<p>We will opt for Declarative transaction management for our example project as it supports most of the features we desire in a transaction manager.<\/p>\n<h2>Here&#8217;s a suggestion for a native paraphrase:<\/h2>\n<p>Example of JDBC Implementation for Spring Transaction Management<\/p>\n<p>We will be creating a Spring JDBC project that involves updating multiple tables in one transaction. The transaction will only be committed if all the JDBC statements execute successfully; otherwise, it will rollback to prevent data inconsistency. If you are familiar with JDBC transaction management, you may argue that this can easily be achieved by setting auto-commit to false for the connection and deciding whether to commit or rollback based on the statements&#8217; results. While this approach is possible, it would result in a significant amount of redundant code for transaction management. Moreover, this code would need to be repeated in all instances where transaction management is required, leading to tightly coupled and difficult-to-maintain code. Spring&#8217;s declarative transaction management solves these concerns by utilizing Aspect Oriented Programming, which offers loose coupling and eliminates the need for excessive code in our application. Let&#8217;s explore how Spring accomplishes this through a simple example. But before we delve into our Spring project, we need to perform some database setup for our purposes.<\/p>\n<h3>Managing transactions in Spring &#8211; Setting up the database.<\/h3>\n<p>We will generate two tables for our purpose and simultaneously update them within a single transaction.<\/p>\n<pre class=\"post-pre\"><code>CREATE TABLE `Customer` (\r\n  `id` int(11) unsigned NOT NULL,\r\n  `name` varchar(20) DEFAULT NULL,\r\n  PRIMARY KEY (`id`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code>CREATE TABLE `Address` (\r\n  `id` int(11) unsigned NOT NULL,\r\n  `address` varchar(20) DEFAULT NULL,\r\n  `country` varchar(20) DEFAULT NULL,\r\n  PRIMARY KEY (`id`)\r\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\r\n<\/code><\/pre>\n<p>We have the option to establish a foreign-key relationship here, linking the Address id column to the Customer id column. However, to keep things simple, I have chosen not to define any constraints. Our Database setup is prepared for the spring transaction management project. Now, let&#8217;s create a basic Spring Maven Project in the Spring Tool Suite. The resulting project structure will resemble the image below. Now, let&#8217;s examine each component individually, as they will collectively demonstrate an example of spring transaction management with JDBC.<\/p>\n<h3>Maven Dependencies for Managing Spring Transactions<\/h3>\n<p>Because we are utilizing the JDBC API, it is necessary to incorporate the spring-jdbc dependency into our application. Additionally, in order to connect to a MySQL database, we will include the mysql-connector-java dependency. The spring-tx artifact provides transaction management dependencies, which are typically included automatically by STS. However, if they are not, they must be included as well. Although there may be other dependencies for logging and unit testing, we will not be utilizing any of them. The code snippet displayed below represents our final pom.xml file.<\/p>\n<pre class=\"post-pre\"><code>&lt;project xmlns=\"https:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"https:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\r\n\t&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n\t&lt;groupId&gt;org.springframework.samples&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;SpringJDBCTransactionManagement&lt;\/artifactId&gt;\r\n\t&lt;version&gt;0.0.1-SNAPSHOT&lt;\/version&gt;\r\n\r\n\t&lt;properties&gt;\r\n\r\n\t\t&lt;!-- Generic properties --&gt;\r\n\t\t&lt;java.version&gt;1.7&lt;\/java.version&gt;\r\n\t\t&lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\r\n\t\t&lt;project.reporting.outputEncoding&gt;UTF-8&lt;\/project.reporting.outputEncoding&gt;\r\n\r\n\t\t&lt;!-- Spring --&gt;\r\n\t\t&lt;spring-framework.version&gt;4.0.2.RELEASE&lt;\/spring-framework.version&gt;\r\n\r\n\t\t&lt;!-- Logging --&gt;\r\n\t\t&lt;logback.version&gt;1.0.13&lt;\/logback.version&gt;\r\n\t\t&lt;slf4j.version&gt;1.7.5&lt;\/slf4j.version&gt;\r\n\r\n\t\t&lt;!-- Test --&gt;\r\n\t\t&lt;junit.version&gt;4.11&lt;\/junit.version&gt;\r\n\r\n\t&lt;\/properties&gt;\r\n\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;!-- Spring and Transactions --&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-context&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring-framework.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-tx&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring-framework.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\r\n\t\t&lt;!-- Spring JDBC and MySQL Driver --&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-jdbc&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring-framework.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;mysql&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;mysql-connector-java&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;5.0.5&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\r\n\t\t&lt;!-- Logging with SLF4J &amp; LogBack --&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;slf4j-api&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${slf4j.version}&lt;\/version&gt;\r\n\t\t\t&lt;scope&gt;compile&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;ch.qos.logback&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;logback-classic&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${logback.version}&lt;\/version&gt;\r\n\t\t\t&lt;scope&gt;runtime&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\r\n\t\t&lt;!-- Test Artifacts --&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-test&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring-framework.version}&lt;\/version&gt;\r\n\t\t\t&lt;scope&gt;test&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;junit&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${junit.version}&lt;\/version&gt;\r\n\t\t\t&lt;scope&gt;test&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\r\n\t&lt;\/dependencies&gt;\r\n&lt;\/project&gt;\r\n<\/code><\/pre>\n<p>As of today, I have made sure to update the Spring versions, so please ensure that the MySQL database driver is compatible with your mysql installation.<\/p>\n<h3>Managing transactions in a Spring framework- Model Classes.<\/h3>\n<p>We are going to develop two Java Beans, namely Customer and Address, which will correspond with our tables.<\/p>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.model;\r\n\r\npublic class Address {\r\n\r\n\tprivate int id;\r\n\tprivate String address;\r\n\tprivate String country;\r\n\t\r\n\tpublic int getId() {\r\n\t\treturn id;\r\n\t}\r\n\tpublic void setId(int id) {\r\n\t\tthis.id = id;\r\n\t}\r\n\tpublic String getAddress() {\r\n\t\treturn address;\r\n\t}\r\n\tpublic void setAddress(String address) {\r\n\t\tthis.address = address;\r\n\t}\r\n\tpublic String getCountry() {\r\n\t\treturn country;\r\n\t}\r\n\tpublic void setCountry(String country) {\r\n\t\tthis.country = country;\r\n\t}\r\n\t\r\n}\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.model;\r\n\r\npublic class Customer {\r\n\r\n\tprivate int id;\r\n\tprivate String name;\r\n\tprivate Address address;\r\n\t\r\n\tpublic int getId() {\r\n\t\treturn id;\r\n\t}\r\n\tpublic void setId(int id) {\r\n\t\tthis.id = id;\r\n\t}\r\n\tpublic String getName() {\r\n\t\treturn name;\r\n\t}\r\n\tpublic void setName(String name) {\r\n\t\tthis.name = name;\r\n\t}\r\n\tpublic Address getAddress() {\r\n\t\treturn address;\r\n\t}\r\n\tpublic void setAddress(Address address) {\r\n\t\tthis.address = address;\r\n\t}\r\n\t\r\n}\r\n<\/code><\/pre>\n<p>When implementing the DAO for the Customer, we must take note that the Customer bean includes the Address as one of its variables. Consequently, when retrieving data for both the customer and address tables, we will need to execute two independent insert queries for each table. To ensure data consistency, it is crucial to have transaction management in place.<\/p>\n<h3>Implementing DAO with Transaction Management in Spring.<\/h3>\n<p>To simplify matters, we will focus on designing the DAO for the Customer bean and have only one method for inserting records in both the customer and address tables.<\/p>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.dao;\r\n\r\nimport com.scdev.spring.jdbc.model.Customer;\r\n\r\npublic interface CustomerDAO {\r\n\r\n\tpublic void create(Customer customer);\r\n}\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.dao;\r\n\r\nimport javax.sql.DataSource;\r\n\r\nimport org.springframework.jdbc.core.JdbcTemplate;\r\n\r\nimport com.scdev.spring.jdbc.model.Customer;\r\n\r\npublic class CustomerDAOImpl implements CustomerDAO {\r\n\r\n\tprivate DataSource dataSource;\r\n\r\n\tpublic void setDataSource(DataSource dataSource) {\r\n\t\tthis.dataSource = dataSource;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void create(Customer customer) {\r\n\t\tString queryCustomer = \"insert into Customer (id, name) values (?,?)\";\r\n\t\tString queryAddress = \"insert into Address (id, address,country) values (?,?,?)\";\r\n\r\n\t\tJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);\r\n\r\n\t\tjdbcTemplate.update(queryCustomer, new Object[] { customer.getId(),\r\n\t\t\t\tcustomer.getName() });\r\n\t\tSystem.out.println(\"Inserted into Customer Table Successfully\");\r\n\t\tjdbcTemplate.update(queryAddress, new Object[] { customer.getId(),\r\n\t\t\t\tcustomer.getAddress().getAddress(),\r\n\t\t\t\tcustomer.getAddress().getCountry() });\r\n\t\tSystem.out.println(\"Inserted into Address Table Successfully\");\r\n\t}\r\n\r\n}\r\n<\/code><\/pre>\n<p>It should be noted that the CustomerDAO implementation does not handle transaction management. By doing this, we ensure a separation of concerns as there are instances where we obtain DAO implementations from external sources and have no control over these classes.<\/p>\n<h3>Spring&#8217;s declarative transaction management for services.<\/h3>\n<p>We can develop a Customer Service that utilizes the CustomerDAO implementation and handles transaction management while inserting records into the customer and address tables within a single method.<\/p>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.service;\r\n\r\nimport com.scdev.spring.jdbc.model.Customer;\r\n\r\npublic interface CustomerManager {\r\n\r\n\tpublic void createCustomer(Customer cust);\r\n}\r\n<\/code><\/pre>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.service;\r\n\r\nimport org.springframework.transaction.annotation.Transactional;\r\n\r\nimport com.scdev.spring.jdbc.dao.CustomerDAO;\r\nimport com.scdev.spring.jdbc.model.Customer;\r\n\r\npublic class CustomerManagerImpl implements CustomerManager {\r\n\r\n\tprivate CustomerDAO customerDAO;\r\n\r\n\tpublic void setCustomerDAO(CustomerDAO customerDAO) {\r\n\t\tthis.customerDAO = customerDAO;\r\n\t}\r\n\r\n\t@Override\r\n\t@Transactional\r\n\tpublic void createCustomer(Customer cust) {\r\n\t\tcustomerDAO.create(cust);\r\n\t}\r\n\r\n}\r\n<\/code><\/pre>\n<p>Simply put, the CustomerManager implementation utilizes the CustomerDAO implementation to create customers. It achieves declarative transaction management by annotating the createCustomer() method with @Transactional. This annotation is enough to enjoy the advantages of Spring transaction management. You can apply @Transactional to individual methods or the entire class if you wish to enable transaction management for all methods. To understand annotations further, refer to the Java Annotations Tutorial. The only remaining step is to wire the spring beans to make the spring transaction management example functional.<\/p>\n<h3>Configuring Beans for Spring Transaction Management<\/h3>\n<p>Generate a Spring Bean Configuration file named &#8220;spring.xml&#8221;. This file will be utilized in our test program to establish connections between spring beans and execute our JDBC program for the purpose of testing transaction management.<\/p>\n<pre class=\"post-pre\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;beans xmlns=\"https:\/\/www.springframework.org\/schema\/beans\"\r\n\txmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:context=\"https:\/\/www.springframework.org\/schema\/context\"\r\n\txmlns:tx=\"https:\/\/www.springframework.org\/schema\/tx\"\r\n\txsi:schemaLocation=\"https:\/\/www.springframework.org\/schema\/beans https:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd\r\n\t\thttps:\/\/www.springframework.org\/schema\/context https:\/\/www.springframework.org\/schema\/context\/spring-context-4.0.xsd\r\n\t\thttps:\/\/www.springframework.org\/schema\/tx https:\/\/www.springframework.org\/schema\/tx\/spring-tx-4.0.xsd\"&gt;\r\n\r\n\t&lt;!-- Enable Annotation based Declarative Transaction Management --&gt;\r\n\t&lt;tx:annotation-driven proxy-target-class=\"true\"\r\n\t\ttransaction-manager=\"transactionManager\" \/&gt;\r\n\r\n\t&lt;!-- Creating TransactionManager Bean, since JDBC we are creating of type \r\n\t\tDataSourceTransactionManager --&gt;\r\n\t&lt;bean id=\"transactionManager\"\r\n\t\tclass=\"org.springframework.jdbc.datasource.DataSourceTransactionManager\"&gt;\r\n\t\t&lt;property name=\"dataSource\" ref=\"dataSource\" \/&gt;\r\n\t&lt;\/bean&gt;\r\n\t\r\n\t&lt;!-- MySQL DB DataSource --&gt;\r\n\t&lt;bean id=\"dataSource\"\r\n\t\tclass=\"org.springframework.jdbc.datasource.DriverManagerDataSource\"&gt;\r\n\r\n\t\t&lt;property name=\"driverClassName\" value=\"com.mysql.jdbc.Driver\" \/&gt;\r\n\t\t&lt;property name=\"url\" value=\"jdbc:mysql:\/\/localhost:3306\/TestDB\" \/&gt;\r\n\t\t&lt;property name=\"username\" value=\"scdev\" \/&gt;\r\n\t\t&lt;property name=\"password\" value=\"scdev123\" \/&gt;\r\n\t&lt;\/bean&gt;\r\n\r\n\t&lt;bean id=\"customerDAO\" class=\"com.scdev.spring.jdbc.dao.CustomerDAOImpl\"&gt;\r\n\t\t&lt;property name=\"dataSource\" ref=\"dataSource\"&gt;&lt;\/property&gt;\r\n\t&lt;\/bean&gt;\r\n\r\n\t&lt;bean id=\"customerManager\" class=\"com.scdev.spring.jdbc.service.CustomerManagerImpl\"&gt;\r\n\t\t&lt;property name=\"customerDAO\" ref=\"customerDAO\"&gt;&lt;\/property&gt;\r\n\t&lt;\/bean&gt;\r\n\r\n&lt;\/beans&gt;\r\n<\/code><\/pre>\n<p>Some key aspects to consider in the spring bean configuration file include:<\/p>\n<ul class=\"post-ul\">\n<li>tx:annotation-driven element is used to tell Spring context that we are using annotation based transaction management configuration. transaction-manager attribute is used to provide the transaction manager bean name. transaction-manager default value is transactionManager but I am still having it to avoid confusion. proxy-target-class attribute is used to tell Spring context to use class based proxies, without it you will get runtime exception with message such as Exception in thread \u201cmain\u201d org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named \u2018customerManager\u2019 must be of type [com.scdev.spring.jdbc.service.CustomerManagerImpl], but was actually of type [com.sun.proxy.$Proxy6]<\/li>\n<li>Since we are using JDBC, we are creating transactionManager bean of type org.springframework.jdbc.datasource.DataSourceTransactionManager. This is very important and we should use proper transaction manager implementation class based on our transaction API use.<\/li>\n<li>dataSource bean is used to create the DataSource object and we are required to provide the database configuration properties such as driverClassName, url, username and password. Change these values based on your local settings.<\/li>\n<li>We are injecting dataSource into customerDAO bean. Similarly we are injecting customerDAO bean into customerManager bean definition.<\/li>\n<\/ul>\n<p>Our configuration is complete, now we can proceed to create a straightforward test class for evaluating our implementation of transaction management.<\/p>\n<pre class=\"post-pre\"><code> com.scdev.spring.jdbc.main;\r\n\r\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\r\n\r\nimport com.scdev.spring.jdbc.model.Address;\r\nimport com.scdev.spring.jdbc.model.Customer;\r\nimport com.scdev.spring.jdbc.service.CustomerManager;\r\nimport com.scdev.spring.jdbc.service.CustomerManagerImpl;\r\n\r\npublic class TransactionManagerMain {\r\n\r\n\tpublic static void main(String[] args) {\r\n\t\tClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(\r\n\t\t\t\t\"spring.xml\");\r\n\r\n\t\tCustomerManager customerManager = ctx.getBean(\"customerManager\",\r\n\t\t\t\tCustomerManagerImpl.class);\r\n\r\n\t\tCustomer cust = createDummyCustomer();\r\n\t\tcustomerManager.createCustomer(cust);\r\n\r\n\t\tctx.close();\r\n\t}\r\n\r\n\tprivate static Customer createDummyCustomer() {\r\n\t\tCustomer customer = new Customer();\r\n\t\tcustomer.setId(2);\r\n\t\tcustomer.setName(\"Pankaj\");\r\n\t\tAddress address = new Address();\r\n\t\taddress.setId(2);\r\n\t\taddress.setCountry(\"India\");\r\n\t\t\/\/ setting value more than 20 chars, so that SQLException occurs\r\n\t\taddress.setAddress(\"Albany Dr, San Jose, CA 95129\");\r\n\t\tcustomer.setAddress(address);\r\n\t\treturn customer;\r\n\t}\r\n\r\n}\r\n<\/code><\/pre>\n<p>Please observe that I intentionally made the address column value excessively long, causing an exception during the insertion of data into the Address table. As a result, when we execute our test program, we receive the subsequent output.<\/p>\n<pre class=\"post-pre\"><code>Mar 29, 2014 7:59:32 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh\r\nINFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3fa99295: startup date [Sat Mar 29 19:59:32 PDT 2014]; root of context hierarchy\r\nMar 29, 2014 7:59:32 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions\r\nINFO: Loading XML bean definitions from class path resource [spring.xml]\r\nMar 29, 2014 7:59:32 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName\r\nINFO: Loaded JDBC driver: com.mysql.jdbc.Driver\r\nInserted into Customer Table Successfully\r\nMar 29, 2014 7:59:32 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions\r\nINFO: Loading XML bean definitions from class path resource [org\/springframework\/jdbc\/support\/sql-error-codes.xml]\r\nMar 29, 2014 7:59:32 PM org.springframework.jdbc.support.SQLErrorCodesFactory &lt;init&gt;\r\nINFO: SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]\r\nException in thread \"main\" org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [insert into Address (id, address,country) values (?,?,?)]; Data truncation: Data too long for column 'address' at row 1; nested exception is com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'address' at row 1\r\n\tat org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:100)\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\r\n\tat org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:658)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:907)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:968)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:978)\r\n\tat com.scdev.spring.jdbc.dao.CustomerDAOImpl.create(CustomerDAOImpl.java:27)\r\n\tat com.scdev.spring.jdbc.service.CustomerManagerImpl.createCustomer(CustomerManagerImpl.java:19)\r\n\tat com.scdev.spring.jdbc.service.CustomerManagerImpl$$FastClassBySpringCGLIB$$84f71441.invoke(&lt;generated&gt;)\r\n\tat org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)\r\n\tat org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:711)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)\r\n\tat org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)\r\n\tat org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)\r\n\tat org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)\r\n\tat org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)\r\n\tat org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)\r\n\tat com.scdev.spring.jdbc.service.CustomerManagerImpl$$EnhancerBySpringCGLIB$$891ec7ac.createCustomer(&lt;generated&gt;)\r\n\tat com.scdev.spring.jdbc.main.TransactionManagerMain.main(TransactionManagerMain.java:20)\r\nCaused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'address' at row 1\r\n\tat com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2939)\r\n\tat com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1623)\r\n\tat com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1715)\r\n\tat com.mysql.jdbc.Connection.execSQL(Connection.java:3249)\r\n\tat com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268)\r\n\tat com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1541)\r\n\tat com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1455)\r\n\tat com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1440)\r\n\tat org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:914)\r\n\tat org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:907)\r\n\tat org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:642)\r\n\t... 16 more\r\n<\/code><\/pre>\n<p>The log message indicates that data was successfully inserted into the customer table, but the exception thrown by the MySQL database driver states that the value is too long for the address column. If you check the Customer table, you will not find any rows, indicating that the transaction has been completely rolled back. The transaction management is being handled by the AOP and Proxy classes created by the Spring framework. Spring is using Around advice to create a proxy class for CustomerManagerImpl and only commits the transaction if the method returns successfully. In case of any exceptions, the entire transaction is rolled back. I recommend reading the Spring AOP Example to learn more about Aspect Oriented Programming. That&#8217;s everything for the Spring Transaction Management Example. You can download the sample project from the link below and explore it further.<\/p>\n<p>Get the Spring JDBC Transaction Management Project downloaded.<\/p>\n<p>&nbsp;<\/p>\n<p>More tutorials<\/p>\n<p><a class=\"LinkSuggestion__Link-sc-1gewdgc-4 cLBplk\" href=\"https:\/\/www.silicloud.com\/blog\/commonly-asked-questions-and-answers-for-hibernate-interviews\/\" target=\"_blank\" rel=\"noopener\">Commonly asked questions and answers for Hibernate interviews<span class=\"sc-gswNZR eASTkv\">(Opens in a new browser tab)<\/span><\/a><\/p>\n<p><a class=\"LinkSuggestion__Link-sc-1gewdgc-4 cLBplk\" href=\"https:\/\/www.silicloud.com\/blog\/a-brief-overview-of-lvm-concepts-terminology-and-procedures\/\" target=\"_blank\" rel=\"noopener\">LVM concepts, terminology, and procedures.<span class=\"sc-gswNZR eASTkv\">(Opens in a new browser tab)<\/span><\/a><\/p>\n<p><a class=\"LinkSuggestion__Link-sc-1gewdgc-4 cLBplk\" href=\"https:\/\/www.silicloud.com\/blog\/the-command-design-pattern\/\" target=\"_blank\" rel=\"noopener\">The Command design pattern.<span class=\"sc-gswNZR eASTkv\">(Opens in a new browser tab)<\/span><\/a><\/p>\n<p><a class=\"LinkSuggestion__Link-sc-1gewdgc-4 cLBplk\" href=\"https:\/\/www.silicloud.com\/blog\/commonly-questions-and-answers-for-a-spring-interview\/\" target=\"_blank\" rel=\"noopener\">Commonly questions and answers for a spring interview.<span class=\"sc-gswNZR eASTkv\">(Opens in a new browser tab)<\/span><\/a><\/p>\n<p><a class=\"LinkSuggestion__Link-sc-1gewdgc-4 cLBplk\" href=\"https:\/\/www.silicloud.com\/blog\/an-instructional-tutorial-on-the-jackson-json-java-parser-api\/\" target=\"_blank\" rel=\"noopener\">An instructional tutorial on the Jackson JSON Java Parser API.<span class=\"sc-gswNZR eASTkv\">(Opens in a new browser tab)<\/span><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is an essential responsibility in any enterprise application. Previously, we learned to handle transactions using the JDBC API. However, Spring offers comprehensive assistance for transaction management, allowing developers to concentrate on their business logic and alleviate [&hellip;]<\/p>\n","protected":false},"author":13,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[],"class_list":["post-1254","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v21.5 (Yoast SEO v21.5) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>An illustration of Spring Transaction Management using JDBC. - Blog - Silicon Cloud<\/title>\n<meta name=\"description\" content=\"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"An illustration of Spring Transaction Management using JDBC.\" \/>\n<meta property=\"og:description\" content=\"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog - Silicon Cloud\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/SiliCloudGlobal\/\" \/>\n<meta property=\"article:published_time\" content=\"2023-11-18T11:52:47+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-03-18T15:08:28+00:00\" \/>\n<meta name=\"author\" content=\"Isabella Edwards\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@SiliCloudGlobal\" \/>\n<meta name=\"twitter:site\" content=\"@SiliCloudGlobal\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Isabella Edwards\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\"},\"author\":{\"name\":\"Isabella Edwards\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/5579144e23c225c8188167f3e3f888dd\"},\"headline\":\"An illustration of Spring Transaction Management using JDBC.\",\"datePublished\":\"2023-11-18T11:52:47+00:00\",\"dateModified\":\"2024-03-18T15:08:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\"},\"wordCount\":1405,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/#organization\"},\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\",\"url\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\",\"name\":\"An illustration of Spring Transaction Management using JDBC. - Blog - Silicon Cloud\",\"isPartOf\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/#website\"},\"datePublished\":\"2023-11-18T11:52:47+00:00\",\"dateModified\":\"2024-03-18T15:08:28+00:00\",\"description\":\"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is\",\"breadcrumb\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.silicloud.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"An illustration of Spring Transaction Management using JDBC.\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#website\",\"url\":\"https:\/\/www.silicloud.com\/blog\/\",\"name\":\"Silicon Cloud Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/#organization\"},\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#organization\",\"name\":\"Silicon Cloud Blog\",\"url\":\"https:\/\/www.silicloud.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.silicloud.com\/blog\/wp-content\/uploads\/2023\/11\/EN-SILICON-Full.png\",\"contentUrl\":\"https:\/\/www.silicloud.com\/blog\/wp-content\/uploads\/2023\/11\/EN-SILICON-Full.png\",\"width\":1024,\"height\":1024,\"caption\":\"Silicon Cloud Blog\"},\"image\":{\"@id\":\"https:\/\/www.silicloud.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/SiliCloudGlobal\/\",\"https:\/\/twitter.com\/SiliCloudGlobal\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/5579144e23c225c8188167f3e3f888dd\",\"name\":\"Isabella Edwards\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d4d4dec47f553ac7961d9fa4cc9bdcdcf5b7ce5106594330b6d25c5694fdbaec?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d4d4dec47f553ac7961d9fa4cc9bdcdcf5b7ce5106594330b6d25c5694fdbaec?s=96&d=mm&r=g\",\"caption\":\"Isabella Edwards\"},\"url\":\"https:\/\/www.silicloud.com\/blog\/author\/isabellaedwards\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"An illustration of Spring Transaction Management using JDBC. - Blog - Silicon Cloud","description":"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/","og_locale":"en_US","og_type":"article","og_title":"An illustration of Spring Transaction Management using JDBC.","og_description":"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is","og_url":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/","og_site_name":"Blog - Silicon Cloud","article_publisher":"https:\/\/www.facebook.com\/SiliCloudGlobal\/","article_published_time":"2023-11-18T11:52:47+00:00","article_modified_time":"2024-03-18T15:08:28+00:00","author":"Isabella Edwards","twitter_card":"summary_large_image","twitter_creator":"@SiliCloudGlobal","twitter_site":"@SiliCloudGlobal","twitter_misc":{"Written by":"Isabella Edwards","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#article","isPartOf":{"@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/"},"author":{"name":"Isabella Edwards","@id":"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/5579144e23c225c8188167f3e3f888dd"},"headline":"An illustration of Spring Transaction Management using JDBC.","datePublished":"2023-11-18T11:52:47+00:00","dateModified":"2024-03-18T15:08:28+00:00","mainEntityOfPage":{"@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/"},"wordCount":1405,"commentCount":0,"publisher":{"@id":"https:\/\/www.silicloud.com\/blog\/#organization"},"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/","url":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/","name":"An illustration of Spring Transaction Management using JDBC. - Blog - Silicon Cloud","isPartOf":{"@id":"https:\/\/www.silicloud.com\/blog\/#website"},"datePublished":"2023-11-18T11:52:47+00:00","dateModified":"2024-03-18T15:08:28+00:00","description":"One of the most crucial and frequently utilized features of the Spring framework is Spring Transaction Management. Managing transactions is","breadcrumb":{"@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.silicloud.com\/blog\/an-illustration-of-spring-transaction-management-using-jdbc\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.silicloud.com\/blog\/"},{"@type":"ListItem","position":2,"name":"An illustration of Spring Transaction Management using JDBC."}]},{"@type":"WebSite","@id":"https:\/\/www.silicloud.com\/blog\/#website","url":"https:\/\/www.silicloud.com\/blog\/","name":"Silicon Cloud Blog","description":"","publisher":{"@id":"https:\/\/www.silicloud.com\/blog\/#organization"},"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.silicloud.com\/blog\/#organization","name":"Silicon Cloud Blog","url":"https:\/\/www.silicloud.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.silicloud.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.silicloud.com\/blog\/wp-content\/uploads\/2023\/11\/EN-SILICON-Full.png","contentUrl":"https:\/\/www.silicloud.com\/blog\/wp-content\/uploads\/2023\/11\/EN-SILICON-Full.png","width":1024,"height":1024,"caption":"Silicon Cloud Blog"},"image":{"@id":"https:\/\/www.silicloud.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/SiliCloudGlobal\/","https:\/\/twitter.com\/SiliCloudGlobal"]},{"@type":"Person","@id":"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/5579144e23c225c8188167f3e3f888dd","name":"Isabella Edwards","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.silicloud.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/d4d4dec47f553ac7961d9fa4cc9bdcdcf5b7ce5106594330b6d25c5694fdbaec?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d4d4dec47f553ac7961d9fa4cc9bdcdcf5b7ce5106594330b6d25c5694fdbaec?s=96&d=mm&r=g","caption":"Isabella Edwards"},"url":"https:\/\/www.silicloud.com\/blog\/author\/isabellaedwards\/"}]}},"_links":{"self":[{"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/posts\/1254","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/comments?post=1254"}],"version-history":[{"count":0,"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/posts\/1254\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/media?parent=1254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/categories?post=1254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.silicloud.com\/blog\/wp-json\/wp\/v2\/tags?post=1254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}