前言:
当前姐妹们对“oracleforallupdate”大概比较注意,兄弟们都需要分析一些“oracleforallupdate”的相关文章。那么小编在网络上汇集了一些关于“oracleforallupdate””的相关资讯,希望姐妹们能喜欢,我们一起来了解一下吧!在实际工作中,经常为用到对某些敏感数据操作进行加锁,常用的锁有悲观锁和乐观锁,这里备忘个数据库层面的悲观锁
for update语句,在数据库中执行select .....for update ,大家会发现会对数据库中的表或某些行数据进行锁表,在mysql中,如果查询条件带有主键,会锁行数据,如果没有,会锁表,在oracle中是对查询范围内的行数据进行锁定。
测试代码
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"";><mapper namespace="com.lovo.mapper.UserMapper"> <resultMap type="UserBean" id="user"> <id property="id" column="id" /> <result property="name" column="u_name" javaType="String"/> <result property="sex" column="u_sex" javaType="String"/> <result property="age" column="u_age" javaType="java.lang.Long"/> </resultMap> <insert id="batchAddUser" parameterType="java.util.List"> insert into t_user (u_id, u_name,u_sex,u_age) (select seq_t_user.nextval,temp.* from ( <foreach collection="list" item="user" separator="union all"> select #{user.name,jdbcType = VARCHAR} u_name, #{user.sex ,jdbcType = VARCHAR} u_sex, #{user.age,jdbcType = NUMERIC} u_age from dual </foreach> ) temp ) </insert> <select id ="selectUserByName" resultMap="user" parameterType="UserBean"> select t.u_id,t.u_name,t.u_sex,t.u_age from t_user t where t.u_name = #{name} for update </select> <update id="updateUserByName" parameterType="java.util.Map"> update t_user t set t.u_age = #{age} where t.u_name =#{name} </update></mapper>
@Override public List<UserBean> selectUserByName(String name) { // 此方法加悲观锁 for update return userMapper.selectUserByName(name); } @Override public void updateUserByName(Map<String, String> date) { userMapper.updateUserByName(date); }
@Service("userService")public class UserServiceImpl implements IUserService { @Autowired @Qualifier(value="userDao") private UserDao userDao; @Override public void updateUserByName(Map<String, String> date) { //悲观锁查询,模拟先查询,锁表然后再更新 List<UserBean> 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<String, String> date = new HashMap<String, String>(); date.put("name", "张三"); date.put("age", "66"); userSerive.updateUserByName(date); }}
这里我们模拟一下,在代码中打一个断点
代码运行完查询语句后会对数据进行锁定
/*查看被锁的表 */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;
发现表有锁定,手工对数据进行修改,发现被查询出的数据锁定,未被查询的数据未锁定,为行级锁
通过断点后锁解除,所以说for update的锁的作用范围为一个会话事物周期内,当执行commit或rollback释放锁定数据。
同样此种用法也适用用编程式事务
首先配置下编程事物
<!-- 配置transactionTemplate 需指定数据源<property name="transactionManager" ref="txManage"></property> --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="txManage"></property> <!--定义事务隔离级别,-1表示使用数据库默认级别--> <property name="readOnly" value="false"></property> <property name="isolationLevelName" value="ISOLATION_DEFAULT"></property> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property> </bean>
@Repository("userDao")public class UserDaoImpl implements UserDao { @Resource private UserMapper userMapper; @Resource private TransactionTemplate transactionTemplate; @Override public void updateUserByNameWithTransaction(final Map<String, String> 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); }}
在代码中打上断点,测试发现在54行断点数据并未commit,在64断点行数据已经commit
有一点需要注意:配置式的事务后,感觉方法的注解事物和编程事物不生效了
初步的预计是,配置的事务管理拦截器优先级较高,使注解式的事务和编程事务没有得到处理。暂时记录这个问题,以后研究 。
标签: #oracleforallupdate