"Java EE Spring" 7, spring operation transaction Management for connection to database

Source: Internet
Author: User
Tags aop connection pooling deprecated

Spring Operations transaction Management for connection to database 1, first of all, we know Spring manages transactions in two ways

Or is it an annotated way of

With @transactional in front of the service class, declare that all methods of the service require transaction management. Each business method starts with a transaction open.

Spring defaults to a transaction rollback of the run-time exception (RuntimeException). The exception is unchecked.

If you encounter a checked accident, do not roll back.

1 Let checked exception also rollback: Add @Transactional (Rollbackfor=exception.class) 2 to the entire method before the unchecked exception is not rolled back: @Transactional ( Notrollbackfor=runtimeexception.class) 3 methods that do not require transaction management (query only): @Transactional (propagation=propagation.not_supported)

The transaction is not opened until the entire method is run and can be added: @Transactional (propagation=propagation.not_supported,readonly=true), which makes a read-only transaction that can improve efficiency.

The meanings of various attributes:

REQUIRED:

The business method needs to be run in a container. If the method is already in a transaction while it is running, join the transaction, or create a new transaction yourself.

Not_supported:

Declaring a method does not require a transaction. If the method is not associated to a transaction, the container does not open the transaction for him, and if the method is called in a transaction, the transaction is suspended and the original transaction resumes execution after the call is finished.

RequiresNew:

Regardless of whether there is a transaction, the method will initiate a new transaction for itself. If the method is already running in a transaction, the old transaction is suspended and the new transaction is created.

MANDATORY:

The method can only be executed in a transaction that already exists, and the business method cannot initiate its own transaction. If called in an environment without transactions, the container throws an exception.

SUPPORTS:

The method is called within the scope of a transaction, and the method becomes part of the transaction. If the method is called outside the scope of the transaction, the method executes in an environment without transactions.

Never:

The method must never be executed within the scope of the transaction. If the exception is thrown. Only if the method is not associated to any transaction will it execute properly.

NESTED:

If an active transaction exists, it is run in a nested transaction. If there is no active transaction, it is performed by the required property. It uses a separate transaction that has multiple savepoint that can be rolled back. The rollback of internal transactions does not affect external transactions. It only works with the Datasourcetransactionmanager transaction manager.

Another is based on the configuration of the XML document, and so we will explain to him and use the test


2, write the program to do the corresponding XML document configuration to understand the spring transaction management

First we need some classes and documentation, and there's the database that I use here for MySQL

Structure diagram:


We write each of them:

Person.java

/** * Function: Implement spring and JDBC Connection * Time: March 26, 2015 21:09:20 * author:cutter_point */package Cn.cutter_point.bean;public class person {private Integer id;private string name;public person () {}//default constructor public person (String name) {this.name = name;} Public Integer GetId () {return ID;} public void SetId (Integer id) {this.id = ID;} Public String GetName () {return name;} public void SetName (String name) {this.name = name;}}

Interface Personservice.java

/** * Function: Implement spring and JDBC Connection * Time: March 26, 2015 21:09:20 * author:cutter_point */package Cn.cutter_point.service;import Java.util.list;import Cn.cutter_point.bean.person;public interface Personservice {/** * Save person * @param person * * public void Save (person person),/** * Update person * @param person */public void Update,/** * Get person by ID * @p Aram PersonID * @return */public person Getperson (Integer personid);/** * get all the person * @return */public List<person> ; Getpersons ();/** * Delete the specified person according to the ID number * @param personid */public void Delete (Integer personid);}

callback function Personrowmapper.java

/** * Function: Implement spring and JDBC Connection * Time: March 26, 2015 21:09:20 * author:cutter_point */package Cn.cutter_point.service.impl;import Java.sql.resultset;import Java.sql.sqlexception;import Org.springframework.jdbc.core.rowmapper;import Cn.cutter_ Point.bean.person;public class Personrowmapper implements RowMapper {@Override//This class has been done at the time of invocation//similar to if (Rs.next) operation, So you don't have to do this here. Public Object Maprow (ResultSet rs, int index) throws SQLException {//This inside we return the result of the query to person person = new Person (r S.getstring ("name"));p Erson.setid (rs.getint ("id")); return person;}}

Transaction Bean File Personservicebean.java

/** * Function: Implement spring and JDBC Connection * Time: March 26, 2015 21:09:20 * author:cutter_point */package Cn.cutter_point.service.impl;import Java.util.list;import Javax.sql.datasource;import Org.springframework.jdbc.core.jdbctemplate;import Cn.cutter_ Point.bean.person;import Cn.cutter_point.service.personservice;public class Personservicebean implements Personservice {//private DataSource datasource;//Here we use a class container in spring JdbcTemplate jdbctemplate;public Personservicebean () {}/** * Set data source * @param dataSource */public void Setdatasource (DataSource dataSource) { This.jdbctemplate = new JdbcTemplate (DataSource);} @Overridepublic void Save (person person) {//TODO auto-generated method Stubjdbctemplate.update (' INSERT into person ' (name ) VALUES (?) ", New Object[]{person.getname ()}, new Int[]{java.sql.types.varchar}); } @Overridepublic void update (person person) {//TODO auto-generated method Stubjdbctemplate.update ("Update person set Nam E=? WHERE id =? ", new Object[]{person.getname (), Person.getid ()}, new Int[]{java.sql.Types.varchar, Java.sql.Types.INTEGER});} @Overridepublic person Getperson (Integer PersonID) {//TODO auto-generated method Stubreturn (person) Jdbctemplate.queryforobject ("select * from person where id =?", New Object[]{personid}, new Int[]{java.sql.types.integer }, New Personrowmapper ());} @Override @suppresswarnings ("unchecked")//The function of this annotation is to cancel the warning of an unchecked conversion, this warning cancels out the public list<person> getpersons () { Return (list<person>) jdbctemplate.query ("SELECT * from person", New Personrowmapper ());} @Overridepublic void Delete (Integer PersonID) {jdbctemplate.update ("Delete from person where id =?", New Object[]{personi D}, new Int[]{java.sql.types.integer}); Jdbctemplate.update ("Delete from personxxx where id =?", New Object[]{personid}, New Int[]{java.sql.types.integer});}}

Here I explain the effect of an annotation inside:

@SuppressWarnings

The last annotation provided by J2SE is @suppresswarnings. The purpose of this annotation is to give the compiler a directive that tells it to remain silent about some of the warnings inside the code element being annotated.

@SuppressWarnings annotations allow you to selectively suppress warnings in specific snippets (that is, classes or methods). The idea is that when you see a warning, you'll investigate it, and if you're sure it's not an issue, you can add a @SuppressWarnings comment so you don't see the warning again. While it may sound like it will block potential errors, it will actually improve code security because it will prevent you from being indifferent to warnings-every warning you see will be worth noting.

Http://zhidao.baidu.com/link?url=srtJ0lOakSMsQotStFzuI46L9ne5k3wUfDT_ediXFlf-H24dR0KVo99qQO1cyWG1oMfVwRVbFv2yWM_oE2-yP_


Keyword usage
Deprecation warning when using a class or method that is deprecated
Unchecked a warning when an unchecked conversion is performed, such as when using a collection without generics (generics) to specify the type of collection to save.
Fallthrough a warning when a Switch block directly leads to the next situation without a break.
The path is a warning when there are no paths in the classpath, source file path, and so on.
Serial a warning when a SERIALVERSIONUID definition is missing on a serializable class.
Finally, a warning when any finally clause does not complete properly.
All warnings about all of these cases.

@SuppressWarnings annotations allow you to selectively suppress warnings in specific snippets (that is, classes or methods). The idea is that when you see a warning, you'll investigate it, and if you're sure it's not an issue, you can add a @SuppressWarnings comment so you don't see the warning again. While it may sound like it will block potential errors, it will actually improve code security because it will prevent you from being indifferent to warnings-every warning you see will be worth noting.

Here is an example of using the @SuppressWarnings to cancel the deprecation warning:

public class DeprecatedExample2 {
@Deprecated
public static void Foo () {
}
}

public class DeprecatedUser2 {
@SuppressWarnings (value={"deprecation"})
public static void Main (string[] args) {
Deprecatedexample2.foo ();
}
}

@SuppressWarnings annotation receives a "value" variable, which is an array of strings that indicates the warning that will be canceled. The collection of legitimate strings varies with the compiler, but on the JDK, the same set of keywords that can be passed to-xlint (very handy). and ask the compiler to ignore any keywords they don't recognize, which is handy when you're using a few different compilers.

Because the @SuppressWarnings annotation only receives one parameter and uses a special name of "value" for the parameter, you can choose to omit value= as a handy abbreviation:

public class DeprecatedUser2 {
@SuppressWarnings ({"Deprecation"})
public static void Main (string[] args) {
Deprecatedexample2.foo ();
}
}

You can pass any number of string values in a single array parameter to the annotation and place the annotation at any level. For example, the following example code indicates that the deprecation warning for the entire class will be canceled, and only the unchecked and Fallthrough warnings are canceled within the main () method code:

Import java.util.*;

@SuppressWarnings ({"Deprecation"})
public class Nongenerics {

@SuppressWarnings ({"Unchecked", "Fallthrough"})
public static void Main (string[] args) {
Runtime.runfinalizersonexit ();

List List = new ArrayList ();
List.add ("foo");
}

public static void Foo () {
List List = new ArrayList ();
List.add ("foo");
}
}

is @SuppressWarnings more useful than the first two annotations? That's absolutely true. However, this annotation is not fully supported in JDK 1.5.0, and if you try it with 1.5.%, then it will resemble a no-action instruction. Calling-xlint:-deprecation also has no effect. Sun does not state when it will add support, but it implies that it will be implemented in a dot version that is about to be launched.

Further

If you try to view these properties in the Javadocs page, you may find it difficult to locate them. They are located in the core Java.lang package, but are somewhat hidden, and they appear at the bottom of the Javadoc class, listed behind Exceptions and Errors.

Have you noticed the unfamiliar annotations @Target and @Retention appended to the suppresswarnings annotation? These are called metadata annotations, and they describe where the annotation applies. I'll cover them in the second article in this series and explain how to apply metadata annotations to your own annotations.

Http://zhidao.baidu.com/link?url=eB0Hyrhazjmnw4INMYlVF4A93hFK42ctoTrdzV5OrFSiJBJceIQlxWvNycq6ESEy8XZFgsyU_9Vd06R0hEHNSK


Test class for JUNIT4

Package Junit.test;import static Org.junit.assert.*;import Org.junit.beforeclass;import Org.junit.test;import Org.springframework.context.applicationcontext;import Org.springframework.context.support.classpathxmlapplicationcontext;import Cn.cutter_point.bean.person;import Cn.cutter_point.service.personservice;public class Personservicetest {private static Personservice personservice;@ Beforeclasspublic static void Setupbeforeclass () throws Exception {try {applicationcontext cxt = new Classpathxmlapplicat Ioncontext ("Beans.xml");p Ersonservice = (personservice) cxt.getbean ("Personservice");} catch (Exception e) {e.printstacktrace ();}} @Testpublic void Save () {for (int i = 0, i < 5; ++i) {Personservice.save (New person ("Xiaofeng" +i));}} @Testpublic void Get () {Person person = Personservice.getperson (7); System.out.println (Person.getname ());} @Testpublic void Update () {Person person = Personservice.getperson (7);p erson.setname ("Shaw X");p ersonservice.update ( person);} @Testpublic void Delete () {PersonservicE.delete (10);} @Testpublic void Getpersons () {for (Person person:personService.getPersons ()) {System.out.println (Person.getname ());}} @Testpublic void Test () {//fail ("not yet implemented");}

Spring configuration file for Beans.xml

<?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: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/sprin G-context-2.5.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP Http://www.springframework.org/schema/aop/spring-ao P-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd "&G t;<!--<bean id= "DataSource" class= "Org.apache.commons.dbcp.BasicDataSource" destroy-method= "Close" > < Property Name= "Driverclassname" VAlue= "Org.gjt.mm.mysql.Driver"/> <property name= "driverclassname" value= "com.mysql.jdbc.Driver"/> Two kinds can be & Lt;property name= "url" value= "Jdbc:mysql://localhost:3306/cutter_point"/>?useunicode=true& Characterencoding=utf-8 <property name= "username" value= "root"/> <property name= "password" value= "xiaofeng2 015 "/> Connection pool Startup initial value <property name=" InitialSize "value=" 1 "/> Connection pool maximum <property name=" maxactive "value=" 500 "  /> maximum idle value. After a peak time, the connection pool can slowly release a portion of the connection that has not been used, and has been reduced to maxidle until <property name= "Maxidle" value= "2"/> Minimum idle value. When the number of idle connections is less than the threshold, the connection pool will be pre-applied to some connections to avoid the flood peak time to apply <property name= "Minidle" value= "1"/> </bean>-< Context:property-placeholder location= "classpath:jdbc.properties"/> <bean id= "DataSource" class= " Org.apache.commons.dbcp.BasicDataSource "destroy-method=" Close "> <property name=" driverclassname "value=" ${ Driverclassname} "/> <property name=" url "value=" ${url} "/><!--? useunicode=true&amP;characterencoding=utf-8--<property name= "username" value= "${username}"/> <property name= "Password" Value= "${password}"/> <!--initial value when connection pooling starts--<property name= "InitialSize" value= "${initialsize}"/><!- -Maximum Connection pool--<property name= "maxactive" value= "${maxactive}"/> <!-- The maximum idle value. After a peak time, the connection pool can slowly release a portion of the connection that has not been used, until it has been reduced to maxidle-<property name= "Maxidle" value= "${maxidle}"/> <!--minimum idle value. When the number of idle connections is less than the threshold, the connection pool will pre-apply for some connections, lest the flood peaks come too late to apply--<property name= "Minidle" value= "${minidle}"/> <     /bean> <bean id= "Txmanager" class= "Org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name= "DataSource" ref= "DataSource"/> </bean> <!--<tx:annotation-driven Transaction-man ager= "Txmanager"/>--<tx:advice id= "Txadvice" transaction-manager= "Txmanager" > <tx:attributes> <tx:method name= "get*" read-only= "true" propagation= "not_supported"/> <!--RequirEsnew: Regardless of whether there is a transaction, the method will initiate a new transaction for itself.   If the method is already running in a transaction, the old transaction is suspended and the new transaction is created.  --<tx:method name= "*"/><!--to handle only the methods that are provided as a get, the rest of the default--</tx:attributes> </tx:advice> <aop:config> <!--AOP Pointcut, expression represents all the methods of all classes that contain sub-packages under the Cn.cutter_point.service package, with or without parameters, with several parameters to intercept- <aop:pointcut expression= "Execution (* cn.cutter_point.service. *.*(..))" Id= "Transactionpointcut"/> <aop:advisor advice-ref= "Txadvice" pointcut-ref= "Transactionpointcut"/><!- -Identify operations and pointcuts for Pointcuts--</aop:config><bean id= "Personservice" class= "Cn.cutter_ Point.service.impl.PersonServiceBean "><property name=" DataSource "ref=" DataSource "/></bean></ Beans>

Then there is the value of the map file, where the ${} placeholder is used in the XML (in the first place, this careless is not the password of its own database exposed!!! )

driverclassname=org.gjt.mm.mysql.driverurl=jdbc\:mysql\://localhost\:3306/cutter_point?useunicode\=true& Characterencoding\=utf-8username=rootpassword=xiaofeng2015initialsize=1maxactive=500maxidle=2minidle=1

And finally the database is set up MySQL

Create Database cutter_point;create table ' cutter_point '. ' Person ' (    ' ID ' int. NOT NULL auto_increment,    ' name ' varchar () Not NULL,     primary key (' ID ')) engine=innodb auto_increment=2 DEFAULT Charset=utf8

Some of the test data in the database, I'm calling the data that was added to the function in the previous test class



OK, so let's explain spring's management of things.



This is our management of the affairs, but how do we know the reason has no effect???

Here we take a look at our delete function, and we'll change the delete function in the Personservicebean class.

public void Delete (Integer PersonID) {     jdbctemplate.update ("Delete from person where id =?", New Object[]{personid}, New Int[]{java.sql.types.integer});     Jdbctemplate.update ("Delete from personxxx where id =?", New Object[]{personid}, New Int[]{java.sql.types.integer}); }

If these two operations are in a transaction, then the following personxxx is not present will definitely error, then delete the transaction rollback then two will be rolled back, then the above bar can not be executed!!!

Let's test it and execute the Personservicetest

public void Delete () {personservice.delete (10);}


Let's see if we can get it. 10th, remove it??


OK program error, stating that the second sentence must be unable to execute, is wrong, but we look at

Are these two sentences in one transaction, or two separate sets of their own affairs?

Let's look at the database!!


is still pure, stating that two statements common one transaction, next we put beans.xml inside the configuration annotation out


We do it again.

Execute the Personservicetest in the

public void Delete () {personservice.delete (10);}
Still wrong,


Finally, let's look at the data inside the database



The data disappears, indicating that the transaction management method for this operation in spring is successful, that is, to commit this as a transaction



Java EE Spring 7, spring operation transaction Management for connection to database

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.