Infinite recursion caused by mybatis level cache

Source: Internet
Author: User

Introduction:

Recently in the project to participate in a coupon collection activities, when multiple users to receive the same coupon, the use of database lock control concurrency, the initial assumption is: if more than one person to receive a coupon, the first person to arrive at the successful, others continue to find out whether there are remaining coupons, if any, continue to collect, Otherwise, the collection fails. In the implementation, I began to use a recursive way to find coupons, the actual test found infinite recursion, through the DEGUG and access to data only found that this is due to the MyBatis cache, the following will be the problem and share the discussion with you.

1. Knowledge Reserves

Brief introduction:

Mybatis

First level cache: Default on, sqlsession level cache, active in current session, Sqlsession commit (), close (), ClearCache () will clear cache after execution.

Second level cache: Requires manual open, global level caching, related to mapper namespace.

For details, see: http://www.mamicode.com/info-detail-890951.html

2. Code examples

Here is an auxiliary method for collecting coupons-randomly extracting a coupon code and invoking the public method of the helper method to open the transaction. During the actual testing process, it is found that infinite recursion occurs when there is only one coupon in the database and is collected by multiple users at the same time. The code is as follows:

1 /**2 * Randomly draw a coupon code3      * 4      * @paramCodeprefix5 * Coupon code prefix6      * @returnCoupon Code9      */Ten     Privatestring Randextractoneticketcode (String mobile, String codeprefix) { OneList<string> notexchangecodelist =yzticketcodedaoext.getticketcodelist (Codeprefix, A mobileserviceconstants.ticket_code_status_not_exchange); -Logger.info ("Collect coupons >>> coupons available Quantity {}", Collectionutils.size (notexchangecodelist)); -         if(Collectionutils.isempty (notexchangecodelist)) { theLogger.warn ("collect coupons >>> coupons {} has been completed", codeprefix); -             Throw Newyzruntimeexception (mobileserviceconstants.ticket_not_remainder); -         } -  +         intRandomindex = Random.nextint (Notexchangecodelist.size ());//Random Index -String Ticketcode = Notexchangecodelist.get (Randomindex);//a randomly selected coupon code +Yzticketcode ticketcodeobj =Yzticketcodedaoext.getbycode (ticketcode); A         if(Ticketcodeobj = =NULL at|| Ticketcodeobj.getstatus ()! =Mobileserviceconstants.ticket_code_status_not_exchange) { -             //if the coupon has been used -Logger.info ("Pick up coupon >>> coupon code {} does not exist or has been used", Ticketcode); -             return Randextractoneticketcode (String mobile, string codeprefix); Recursive lookup -         } -         /* in * Update promo code status -          */ to Ticketcodeobj.setexchangetime (Calendar.getinstance (). GetTime ()); + Ticketcodeobj.setstatus (mobileserviceconstants.ticket_code_status_had_exchanged); - ticketcodeobj.setmobile (mobile); the         intupdatecnt =yzticketcodedaoext.update4receive (ticketcodeobj); *         if(updatecnt <= 0){ $             //optimistic lock, does not affect the row, indicates that the update failed, may be that the coupon does not exist or has been usedPanax NotoginsengLogger.info ("Pick up coupon >>> coupon code {} does not exist or has been used", Ticketcode); -             return Randextractoneticketcode (String mobile, string codeprefix); Recursive lookup the         }; +         returnTicketcode; A}

Debug found that the query results executed by line 11th are mybatis cached, so each time a coupon can be picked up, but in fact this coupon has been picked up by other users, resulting in infinite recursion.

3. Solution

1) Programmatic transactions, get sqlsession through TransactionManager, and then clear the first-level cache through the sqlsession ClearCache () method.

2) because the project uses spring-declared transactions, and the concurrency is not high, considering the reduction of complexity, the direct prompt user system is busy.

/*** Randomly draw a coupon code * *@paramcodeprefix * Promo code prefix *@returnCoupon Code *@throwsyzruntimeexception * If no coupon is available*/    Privatestring Randextractoneticketcode (String mobile, String codeprefix) {List<String> notexchangecodelist =yzticketcodedaoext.getticketcodelist (Codeprefix, Mobileserviceconstants.ticket_code_status_not_exchang        E); Logger.info ("Pick up coupon >>> coupon available Quantity {}", Collectionutils.size (notexchangecodelist)); if(Collectionutils.isempty (notexchangecodelist)) {Logger.warn ("Collect coupons >>> coupons {} has been completed", Codeprefix); Throw Newyzruntimeexception (Mobileserviceconstants.ticket_not_remainder); }        intRandomindex = Random.nextint (Notexchangecodelist.size ());//Random IndexString Ticketcode = Notexchangecodelist.get (Randomindex);//a randomly selected coupon codeYzticketcode ticketcodeobj =Yzticketcodedaoext.getbycode (Ticketcode); if(Ticketcodeobj = =NULL|| Ticketcodeobj.getstatus ()! =Mobileserviceconstants.ticket_code_status_not_exchange) {            //if the coupon has been usedLogger.info ("Pick up coupon >>> coupon code {} does not exist or has been used", Ticketcode); Throw Newyzruntimeexception (mobileserviceconstants.ticket_system_busy); }        /** Update promo code status*/Ticketcodeobj.setexchangetime (Calendar.getinstance (). GetTime ());        Ticketcodeobj.setstatus (mobileserviceconstants.ticket_code_status_had_exchanged);        Ticketcodeobj.setmobile (mobile); intupdatecnt =yzticketcodedaoext.update4receive (ticketcodeobj); if(updatecnt <= 0){            //optimistic lock, does not affect the row, indicates that the update failed, may be that the coupon does not exist or has been usedLogger.info ("Pick up coupon >>> coupon code {} does not exist or has been used", Ticketcode); Throw Newyzruntimeexception (mobileserviceconstants.ticket_system_busy);        }; returnTicketcode; }

Infinite recursion caused by mybatis level cache

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.