oracle如何写悲观锁,Spirng oracle 中for update悲观锁及事务

在实际工作中,经常为用到对某些敏感数据操作进行加锁,常用的锁有悲观锁和乐观锁,这里备忘个数据库层面的悲观锁

for update语句,在数据库中执行select .....for update ,大家会发现会对数据库中的表或某些行数据进行锁表,在mysql中,如果查询条件带有主键,会锁行数据,如果没有,会锁表,在oracle中是对查询范围内的行数据进行锁定。

测试代码

/p>

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

insert into t_user (u_id, u_name,u_sex,u_age)

(select

seq_t_user.nextval,temp.* from (

select

#{user.name,jdbcType = VARCHAR} u_name,

#{user.sex ,jdbcType = VARCHAR} u_sex,

#{user.age,jdbcType = NUMERIC} u_age

from dual

) temp

)

select t.u_id,t.u_name,t.u_sex,t.u_age from t_user t where t.u_name = #{name} for update

update t_user t set t.u_age = #{age} where t.u_name =#{name}

@Override

public List selectUserByName(String name) {

// 此方法加悲观锁 for update

return userMapper.selectUserByName(name);

}

@Override

public void updateUserByName(Map date) {

userMapper.updateUserByName(date);

}

@Service("userService")

public class UserServiceImpl implements IUserService {

@Autowired

@Qualifier(value="userDao")

private UserDao userDao;

@Override

public void updateUserByName(Map date) {

//悲观锁查询,模拟先查询,锁表然后再更新

List userList = userDao.selectUserByName(date.get("name"));

System.out.println(userList);

userDao.updateUserByName(date);

}

}

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = "classpath*:applicationContext.xml")

public class TransactionTest {

@Autowired

@Qualifier(value="userService")

private IUserService userSerive;

@Test

public void test()

{

Map date = new HashMap();

date.put("name", "张三");

date.put("age", "66");

userSerive.updateUserByName(date);

}

}

这里我们模拟一下,在代码中打一个断点

26c1fce9a11b

image.png

代码运行完查询语句后会对数据进行锁定

/*查看被锁的表 */

select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;

26c1fce9a11b

image.png

发现表有锁定,手工对数据进行修改,发现被查询出的数据锁定,未被查询的数据未锁定,为行级锁

26c1fce9a11b

image.png

通过断点后锁解除,所以说for update的锁的作用范围为一个会话事物周期内,当执行commit或rollback释放锁定数据。

同样此种用法也适用用编程式事务

首先配置下编程事物

@Repository("userDao")

public class UserDaoImpl implements UserDao {

@Resource

private UserMapper userMapper;

@Resource

private TransactionTemplate transactionTemplate;

@Override

public void updateUserByNameWithTransaction(final Map date) {

//测试编程事物

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

@Override

protected void doInTransactionWithoutResult(TransactionStatus status) {

try

{

System.out.println(userMapper.selectUserByName(date.get("name")));

userMapper.updateUserByName(date);

} catch (Exception e)

{

//异常事务回滚

status.setRollbackOnly();

e.printStackTrace();

}

}

});

userMapper.updateUserByName(date);

}

}

26c1fce9a11b

image.png

在代码中打上断点,测试发现在54行断点数据并未commit,在64断点行数据已经commit

有一点需要注意:配置式的事务后,感觉方法的注解事物和编程事物不生效了

初步的预计是,配置的事务管理拦截器优先级较高,使注解式的事务和编程事物没有得到处理。暂时记录这个问题,以后研究 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值