Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Transaction management using @ Transactional annotation of Spring in SSM framework

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)06/01 Report--

An introduction

In enterprise applications, it is very important to protect the integrity of data. Therefore, no matter how high the performance of the application is and how beautiful the interface is, if there is an unexpected error in the amount of the user's account during the transfer process, then such an application is also unacceptable.

Database transaction management can effectively protect data integrity (PS: about the database transaction management basis can refer to my previous article: http://www.zifangsky.cn/385.html), but the original transaction operation needs to write a lot of code, which is undoubtedly very troublesome. In applications that use the Spring framework, we can use the @ Transactional annotation to easily perform transaction operations, such as transaction rollback. Next, I'll give an example of transaction annotation operations in the SSM framework:

2 the construction of the test project

(1) the project structure and the jar package used:

(2) the SQL file used in the test:

SET FOREIGN_KEY_CHECKS=0;---Table structure for user---DROP TABLE IF EXISTS `user` CREATE TABLE `user` (`id` int (11) NOT NULL AUTO_INCREMENT, `name` varchar (32) DEFAULT NULL, `password` varchar (64) DEFAULT NULL, `email` varchar (64) DEFAULT NULL, `day` date DEFAULT NULL, `money`decimal (15Lin2) DEFAULT NULL, PRIMARY KEY (`id`) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 -Records of user-- INSERT INTO `user`VALUES ('1x, 'admin',' 123456, 'admin@qq.com',' 2000-01-02, '1000.00') INSERT INTO `user`VALUES ('2mm,' test', '12344th,' test@zifangsky.cn', '1990-12-1231,' 2500.00'); INSERT INTO `user`VALUES ('32nd,' xxxx', 'xx',' xx@zifangsky.cn', '1723-06-21mm,' 4000.00')

(3) use mybatis-generator combined with Ant script to generate Model, Mapper and other files quickly and automatically:

You can refer to an article I wrote in the past, but I won't say much about it here. Portal: http://www.zifangsky.cn/431.html

(4) some basic configuration files:

I) web.xml:

ContextConfigLocation classpath:context/context.xml org.springframework.web.context.ContextLoaderListener org.springframework.web.context.request.RequestContextListener springmvc org.springframework. Web.servlet.DispatcherServlet contextConfigLocation classpath:context/jsp-dispatcher.xml 1 springmvc * .html characterEncodingFilter org.springframework.web .filter.CharacterEncodingFilter encoding UTF-8 characterEncodingFilter / *

Ii) jdbc configuration file jdbc.properties:

Master.jdbc.driverClassName=com.mysql.jdbc.Drivermaster.jdbc.url=jdbc:mysql://127.0.0.1:3306/transaction#usermaster.jdbc.username=rootmaster.jdbc.password=root

Iii) context.xml:

Classpath:jdbc.properties ${master.jdbc.driverClassName} ${master.jdbc.url} ${master.jdbc.username} ${master.jdbc.password} 5 30 10 60 5 0 60 30 True false

In the above configuration, C3P0 is used as the database connection pool, and automatic scanning annotations, Mybatis-related configurations and declarative transaction management are defined. If you are not familiar with these basics, you can refer to some articles I have written before.

Iv) jsp-dispatcher.xml:

/ WEB-INF/jsp/ .jsp

V) sql-map-config.xml:

(5) the project environment built by testing:

I) add several basic interfaces to the UserManager.java interface:

Public interface UserManager {int deleteByPrimaryKey (Integer id); int insert (User record); int insertSelective (User record); User selectByPrimaryKey (Integer id); int updateByPrimaryKeySelective (User record); int updateByPrimaryKey (User record);}

Ii) UserManagerImpl.java:

Package cn.zifangsky.manager.impl;import java.math.BigDecimal;import javax.annotation.Resource;import org.apache.ibatis.jdbc.RuntimeSqlException;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import cn.zifangsky.manager.UserManager;import cn.zifangsky.mapper.UserMapper;import cn.zifangsky.model.User;@Service (value= "userManagerImpl") public class UserManagerImpl implements UserManager {@ Resource (name= "userMapper") private UserMapper userMapper Public int deleteByPrimaryKey (Integer id) {return 0;} public int insert (User record) {return 0;} public int insertSelective (User record) {return 0;} public User selectByPrimaryKey (Integer id) {return userMapper.selectByPrimaryKey (id) } public int updateByPrimaryKeySelective (User record) {return 0;} public int updateByPrimaryKey (User record) {return 0;}}

Iii) UserController.java:

Package cn.zifangsky.controller;import java.math.BigDecimal;import javax.annotation.Resource;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import cn.zifangsky.manager.UserManager;import cn.zifangsky.model.User;@Controllerpublic class UserController {@ Resource (name = "userManagerImpl") private UserManager userManager @ RequestMapping (value = "/ select") public String user (@ RequestParam (name = "userId", required = false) Integer userId) {User user = userManager.selectByPrimaryKey (userId); System.out.println ("user name:" + user.getName ()); System.out.println ("mailbox:" + user.getEmail ()); return "success" }}

Iv) start the project and test:

Visit: http://localhost:8090/TransactionDemo/select.html?userId=2 after the project starts. If you find the following output in the console, the test environment has been successfully built:

User name: test mailbox: test@zifangsky.cn 3 uses @ Transactional annotation to manage transaction example

(1) add the following method to the UserManager API:

/ * transfer * * @ param sourceAccountId * Source account * @ param targetAccountId * Target account * @ param amount * transfer amount * / void transferMoney (Integer sourceAccountId, Integer targetAccountId, BigDecimal amount)

The purpose of this method is to simulate the transfer operation.

(2) add the corresponding implementation method to the UserManagerImpl implementation class:

@ Transactional (rollbackFor=Exception.class) public void transferMoney (Integer sourceAccountId, Integer targetAccountId, BigDecimal amount) {User sourceAccount = userMapper.selectByPrimaryKey (sourceAccountId); User targetAccount = userMapper.selectByPrimaryKey (targetAccountId); BigDecimal sourceMoney = sourceAccount.getMoney (); BigDecimal targetMoney = targetAccount.getMoney () / / determine whether the account balance is sufficient if (sourceMoney.compareTo (amount) > 0) {sourceAccount.setMoney (sourceMoney.subtract (amount)); targetAccount.setMoney (targetMoney.add (amount)) / / Update database userMapper.updateByPrimaryKeySelective (sourceAccount); throw new RuntimeSqlException ("exception occurred during manual simulation transfer"); / / userMapper.updateByPrimaryKeySelective (targetAccount);}}

As you can see, a @ Transactional is declared on this method, indicating that the method is going to do transaction management, and it needs to be noted that the rollbackFor parameter defines the rollback of the transaction in the event of an exception. Obviously, what is defined here is that all Exception are subject to transaction rollback. The opposite parameter is norollbackFor, so I won't say much here. For the @ Transactional annotation, we can not only place it on a method, but also declare it on the class. If you use this annotation at the class level, all public methods in the class are transactional, otherwise only public methods that use the @ Transactional annotation are transactional

In this method, in order to simulate an exception in the transfer, an exception is thrown manually after the first account is updated.

(3) add a method to simulate transfer in the UserController class:

@ RequestMapping (value = "/ transfer") public String transfer (@ RequestParam (name = "account1") Integer account1, @ RequestParam (name = "account2") Integer account2, @ RequestParam (name = "amount") Long amount) {System.out.println ("before transfer:"); System.out.println ("funds for account one:" + userManager.selectByPrimaryKey (account1). GetMoney (). LongValue ()) System.out.println ("funds of account II:" + userManager.selectByPrimaryKey (account2). GetMoney (). LongValue ()); / / transfer userManager.transferMoney (account1, account2, BigDecimal.valueOf (amount)); System.out.println ("after transfer:") System.out.println ("funds for account one:" + userManager.selectByPrimaryKey (account1). GetMoney (). LongValue (); System.out.println ("funds for account two:" + userManager.selectByPrimaryKey (account2). GetMoney (). LongValue ()); return "success";}

(4) effect test:

Visit: http://localhost:8090/TransactionDemo/transfer.html?account1=1&account2=2&amount=500 after the project is running

You can find that the project will be saved, so let's check the database to see if the amount in account 1 and account 2 has changed:

It can be seen that the amounts of both have not changed, indicating that things have indeed rolled back. Of course, interested students can remove the @ Transactional annotation from UserManagerImpl to see if the amount in the database will change after the "transfer".

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report