JdbcTemplate and transaction Management
The jdbctemplate operation uses the JDBC default autocommit mode, which means that we cannot guarantee the atomicity of the data operation (either full or invalid), such as:
JdbcTemplate jdbctemplate = new JdbcTemplate (DataSource);
Jdbctemplate.update ("update user SET age = ten WHERE id = ' Erica '");
Jdbctemplate.update ("update user SET age = age+1 WHERE id = ' Erica '");
Since the autocommit mode is used, the first update operation is automatically submitted, and the corresponding record of "Erica" in the database has been updated, and if the second operation fails, we cannot roll the entire transaction back to its original state. This example may not matter, but for a financial accounting system, such problems can lead to fatal errors.
In order to realize the atomicity of data manipulation, we need to introduce transaction logic into the program, and introduce transaction mechanism into JdbcTemplate, there are two ways in spring:
1. Code-controlled transaction management
2. Transaction management for parameterized configuration
Here are two ways to do this.
Code-controlled transaction management
First, make the following configuration, assuming the configuration file is (application-context.xml):
<beans>
<bean id= "DataSource" class= "Org.apache.commons.dbcp.BasicDataSource" destroy-method= "Close" >
<property name= "Driverclassname" >
<value>net.sourceforge.jtds.jdbc.Driver</value>
</property>
<property name= "url" >
<value>jdbc:jtds:sqlserver://127.0.0.1:1433/Sample</value>
</property>
<property name= "username" >
<value>test</value>
</property>
<property name= "Password" >
<value>changeit</value>
</property>
</bean>
<bean id= "TransactionManager" class= "Org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name= "DataSource" >
<ref local= "DataSource"/>
</property>
</bean>
<bean id= "Userdao" class= "Net.xiaxin.dao.UserDAO" >
<property name= "DataSource" >
<ref local= "DataSource"/>
</property>
<property name= "TransactionManager" >
<ref local= "TransactionManager"/>
</property>
</bean>
</beans>
Three nodes are included in the configuration:
Ødatasource
Here we use the DataSource implementation provided by the Apache DHCP component and configure it with
Parameters such as JDBC driver, database URL, username and password.
Øtransactionmanager
For the JDBC DataSource type of data source, we chose the
Datasourcetransactionmanager
As a transaction management component.
If you need to use a container based data source (JNDI), we can use the following configuration:
<bean id= "DataSource" class= "Org.springframework.jndi.JndiObjectFactoryBean" >
<property name= "Jndiname" >
<value>jdbc/sample</value>
</property>
</bean>
<bean id= "TransactionManager" class= "Org.springframework.transaction.jta.JtaTransactionManager"/>
Øuserdao
Declares a Userdao Bean and assigns it a DataSource and
Transactionmanger Resources.
Userdao corresponds to the following code: public class Userdao {
Private DataSource DataSource;
Private Platformtransactionmanager TransactionManager;
Public Platformtransactionmanager Gettransactionmanager () {
return TransactionManager;
}
public void Settransactionmanager (Platformtransactionmanager transactionmanager) {
This.transactionmanager = TransactionManager;
}
Public DataSource Executetestsource () {
Return DataSource
}
public void Setdatasource (DataSource DataSource) {
This.datasource = DataSource;
}
public void Insertuser () {
Transactiontemplate tt = new Transactiontemplate (Gettransactionmanager ());
Tt.execute (New Transactioncallback () {
Public Object dointransaction (transactionstatus status) {
JdbcTemplate JT = new JdbcTemplate (Executetestsource ());
Jt.update ("INSERT into users (username) values (' Xiaxin ');");
Jt.update ("INSERT into users (Id,username) VALUES (2, ' Erica ');");
return null;
}
});
}
}
As you can see, in the Insertuser method, we introduce a new template class: Org.springframework.transaction.support.TransactionTemplate. Transactiontemplate encapsulates the functions of transaction management, including transaction rollback when the exception occurs, and transaction commits after the successful operation. Like JdbcTemplate, it makes it unnecessary to wander through trivial try/catch/finally code.
An operation in dointransaction that throws an unhandled exception will be automatically rolled back, and will be automatically submitted if it is executed successfully.
Here we deliberately create some exceptions to see if the database operation is rolled back (by intentionally triggering an exception by updating the Self-ID field in the second statement):
Write a simple testcase to observe the actual effect:
InputStream is = new FileInputStream ("Application-context.xml");
Xmlbeanfactory factory = new Xmlbeanfactory (IS);
Userdao Userdao = (Userdao) factory.getbean ("Userdao");
Userdao.insertuser ();
I believe that the above code is a bit messy, callback writing seems to be contrary to the day-to-day programming habits (although I think this method is more interesting, because it cleverly solves the author in the early development of data access template for the problem).
How to further avoid these problems. Spring's container transaction management mechanism is here to show its powerful energy.
U-parameterized Configuration Transaction management
Add a transaction agent (Userdaoproxy) configuration to the above Application-context.xml and, because the transaction is managed by the container, Userdao no longer needs TransactionManager settings to remove it:
<bean id= "Userdaoproxy"
Class= "Org.springframework.transaction.interceptor.Transac
Tionproxyfactorybean ">
<property name= "TransactionManager" >
<ref bean= "TransactionManager"/>
</property>
<property name= "Target" >
<ref local= "Userdao"/>
</property>
<property name= "Transactionattributes" >
<props>
<prop key= "insert*" >PROPAGATION_REQUIRED</prop>
<prop key= "*" >PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id= "Userdao" class= "Net.xiaxin.dao.UserDAO" >
<property name= "DataSource" >
<ref local= "DataSource"/>
</property>
</bean>
In the above configuration, the Userdaoproxy node is configured with a transaction agent for the Userdao bean (specified by the target attribute).
With the Transactionattributes property, we specify the management policy for the transaction, that is, all transactions that begin with insert, and if the managed method throws an exception, the transaction in the method is automatically rolled back and, if executed successfully, the transaction is committed after the method completes. On the other hand, for other methods (represented by wildcards *), read-only transaction management is performed to achieve better performance.
Accordingly, Userdao.insertuser's code is modified as follows:
public void Insertuser (Registerinfo reginfo) {
JdbcTemplate JT = new JdbcTemplate (Executetestsource ());
Jt.update ("INSERT into users (username) values (' Xiaxin ');");
Jt.update ("INSERT into users (Id,username) VALUES (2, ' Erica ');");
}
The test code is modified as follows:
InputStream is = new FileInputStream ("Application-context.xml");
Xmlbeanfactory factory = new Xmlbeanfactory (IS);
Note that it is necessary to obtain a reference through the proxy bean "Userdaoproxy" instead of the direct Getbean ("Userdao")
In addition there is a potential problem with forced transitions, see hibernate in Spring One
A supplementary description of the compulsory transition.
Userdao Userdao = (Userdao) factory.getbean ("Userdaoproxy");
Userdao.insertuser ();
As you can see, Insertuser has become very concise. Data logic is clearly visible, compared to the previous code-controlled transaction management, as well as traditional JDBC operation, I believe that we will have some quickly cheerful feeling.
Careful readers will say that this simply shifts the code to the configuration file and does not reduce the amount of work. This distinction may not be important, and the configuration of transactional management is clearly more advantageous from the standpoint of application maintenance. Moreover, the actual development, if the early design of meticulous, the method of transaction characteristics of the general will not occur after the big changes, and then frequent maintenance process, we only need to face the code in the data logic can be.
In conjunction with JdbcTemplate, we describe the template operations and transaction management mechanisms in spring. Spring as an open platform for application development. It also provides good support for other components. In the persistence layer, Spring provides template implementations for Hibernate, Ibatis, and JDO, and these implementations also provide strong support for our development.