Scenario: Spring+ibatis environment, using Spring AOP transactions (configured to service layer), in one service method, customizing a multi-threaded, resulting transaction does not work, without threads, the transaction is valid.
Cause: Spring's transaction is guaranteed to be thread-safe through threadlocal, and the transaction is bound to the current thread, so it is natural for the transaction to be invalidated by its own multithreading.
Spring's transaction manager uses Threadlocal to save a copy of each thread for thread-safe, combined with IOC and AOP for advanced declarative transactions, so spring's transactions are inextricably linked to threads. You can only maintain multi-threading for Web apps, not multithreading in multithreading.
Other scenarios: Modify the code schema, extract the logical processing part, put it in another service, and then call ( thread operations outside the scope of the transaction) by Xxx.service method, so that there is a transaction.
Application scenario: Iterate over the historical data, add the processing to the database, or throw an exception (if you do not use multi-threading, you can do a batch of data or all succeed, and a failure is all rolled back).
The code snippet is as follows:
Code a Reclaimmatchsubscriptionserviceimpl,
private void Savehistorymatches (final matchedinfoparams params, final commontaskname taskname, final List<integer > Matchids) { new Thread () { @Override public void Run () { Matchedinfoparams clonedparams = Params.clone (); For (final Integer matchid:matchids) { try { clonedparams.setmatchid (matchid); Saveworkingtask (Clonedparams, TaskName, Taskpriority.low); } catch (Exception e) { logger.error ("Save history matches to working task Failed:matchedid=" + Matchid + ", companyid= "+ Params.getcompanyid () +", taskname= "+ taskname +", matchtype= "+ params.getmatchtype (), E); } } } }. Start (); }
public void Saveworkingtask (T params, commontaskname TaskName, taskpriority priority) {Assert.notnull (params, "Com Montaskparams must not being null "); Assert.notnull (TaskName, "commontaskname must not being null"); Assert.notnull (priority, "taskpriority must is not null"); if (Isservicetodeal (TaskName)) {String UniqueKey = new MD5 (). MD5 (UniqueKey (params)); Workingcommontask oldtask = Commontaskservice.getworkingtaskbynameandkey (TaskName, UniqueKey); if (Isaddtoworkingtask (Oldtask)) {workingcommontask task = new Workingcommontask (); Task.setcompanyid ( Params.getcompanyid ()); Task.settaskname (Taskname.getcode ()); Task.setuniquekey (UniqueKey); Task.setretrievalfield (Retrievalfield (params));//task.setextrainfo (""); Task.setretrycount (0); Task.settaskpriority (Priority.getcode ()); Task.settaskstatus (CommonTaskStatus.CREATED.getCode ()); Task.settimeout (0); Commontaskservice.saveworkingtask (Task, getbiz (params));}} }
Code two Commontaskserviceimpl,
public int Saveworkingtask (Workingcommontask workingtask, String bizdata) { assert.notnull (Workingtask, " Workingtask must not being null "); Assert.notnull (BizData, "bizdata must not being null"); if (workingtask.gettimeout () <= 0) { workingtask.settimeout (timeout); } int taskId = Commontaskdao.saveworkingtask (workingtask); Commontaskextrainfo taskextrainfo = new Commontaskextrainfo (); Taskextrainfo.settaskid (taskId); Taskextrainfo.setbizdata (bizdata); Commontaskdao.savetaskextrainfo (taskextrainfo); Commontaskdao.savetasklog (New Commontasklog (TaskId, Workingtask.gettaskstatus (), Workingtask.getextrainfo ())); return taskId; }
Spring transactions and custom multithreading traps