标签:
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" />
在指定代码处添加事务注解
@Transactional @Override public boolean increaseBalanceByLock(Long userId, BigDecimal amount) throws ValidateException { long time = System.currentTimeMillis(); //获取对记录的锁定 UserBalance balance = userBalanceDao.getLock(userId); LOGGER.info("[lock] start. time: {}", time); if (null == balance) { throw new ValidateException( ValidateErrorCode.ERRORCODE_BALANCE_NOTEXIST, "user balance is not exist"); } boolean result = userBalanceDao.increaseBalanceByLock(balance, amount); long timeEnd = System.currentTimeMillis(); LOGGER.info("[lock] end. time: {}", timeEnd); return result; }
MyBatis中的锁定方式,实际测试该方法确实可以有效控制,不过在大并发量的情况下,可能会有性能问题吧
<select id="getLock" resultMap="BaseResultMap" parameterType="java.lang.Long"> <![CDATA[ select * from user_balance where id=#{id,jdbcType=BIGINT} for update; ]]> </select>
update user_balance set Balance = #{balance,jdbcType=DECIMAL},Version = Version+1 where Id = #{id,jdbcType=BIGINT} and Version = #{version,jdbcType=BIGINT}
这是一种不使用数据库锁的方法,解决方式也很巧妙。当然,在大量并发的情况下,一次扣款需要重复多次的操作才能成功,还是有不足之处的。不知道还有没有更好的方法。
标签:
原文地址:http://www.cnblogs.com/naiyou/p/5643746.html