Hibernate乐观锁、Mysql读锁/共享锁、写锁/排他锁、hibernate整合log4j日志、一对一外键、主键配置、hibernate二级缓存、hibernate整合ehcache-day05

第一节 Mysql悲观锁

  • 悲观锁分为下面这两种锁,读锁与写锁。

1.1 读锁/共享锁【用的少】

  • 读锁可被其它线程所共享,如果是读取,大家都可以用这把锁读到数据。
  • select * from table lock in share mode;#(读锁、共享锁)
  • 演示步骤:(终端左A右B)
  1. A终端开启事务添加读锁,此时A拿到锁(共享锁,都可以拿)
  2. B终端开启事务添加读锁,此时B拿到锁,锁在B中
  3. A终端执行更新操作,不执行,要等待B提交事务后(释放锁),A才能执行,否则A一直等待直到超时(超时后也不更新)
  4. B终端提交后,A才执行更新
  5. A终端提交,结束

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#开启事务
START TRANSACTION;
#添加读锁或者共享锁,其它线程可以用这把锁
SELECT * FROM t_customer LOCK IN SHARE MODE;
#如果其它线程用了这把锁,没有提交或释放锁,不能执行更新
UPDATE t_customer SET `customerName` = 'shuyy' WHERE customerId=1;
#提交事务
COMMIT;

1.2 写锁/排他锁【用的多】

  • 写锁不能共享,只要有人为这个数据加入了写锁,其他人就不能为该数据加任何锁。

  • select * from table for update; #(写锁、排它锁)

  • 该锁可以锁一张表,或者锁一行记录

  • 演示步骤:(终端左A右B)

  1. A终端开事务添加写锁
  2. B终端开事务读表添加写锁【读不到数据】
  3. A终端更新
  4. A终端提交
  5. B终端提交
  • 锁表
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 锁一条记录
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
#开启事务
START TRANSACTION;
#给表添加写锁,其它线程无法读取这个表,当提交后才可以读取这个表
#锁表【不推荐使用】
SELECT * FROM t_customer FOR UPDATE; 
#锁一条记录【常用】例如:对钱的操作
SELECT * FROM t_customer WHERE customerId=1 FOR UPDATE;
#把这条记录锁住后别人不能更新不能添加锁,可以查看到,必须要等操作那一条记录的事务提交后才能操作这条记录
#更新
UPDATE t_customer SET `customerName` = 'shuyy1' WHERE customerId=1;
#提交事务
COMMIT;

1.3 hibernate中使用写锁

通过get添加写锁

	//写锁/排他锁(别人拿不到的锁)的实现
    @Test
    public void test1(){
   
        Session session = HibernateUtils.openSession();
        //开启事务
        session.beginTransaction();
        //给行添加写锁,如:SELECT * FROM t_customer WHERE customerId=1 FOR UPDATE;
        Customer customer = (Customer) session.get(Customer.class, 1, LockOptions.UPGRADE);
        //session.get(Customer.class,1, LockOptions.READ);//读锁
        System.out.println(customer);
        //提交事务
        session.getTransaction().commit();
        session.close();
    }
  • 在终端开启事务给行添加写锁,再运行程序,程序不会执行(虽然打印了sql但是程序并未执行)会等待终端commit提交事务,否则到超时也不会执行
    在这里插入图片描述
  • 终端提交后,程序会立马执行,能够给行加锁(这里的程序运行完就提交事务了)
    在这里插入图片描述

注意:这里虽然是在sql后添加 for update实现写锁,但是hql中不能这么直接在hql后写,否则报错。
在这里插入图片描述

通过query添加写锁

//写锁/排他锁的注意事项
    @Test
    public void test2(){
   
        Session session = HibernateUtils.openSession();
        //开启事务
        session.beginTransaction();
        Query query = session.createQuery("from Customer where id = ?");
        //Query query = session.createQuery("from Customer where id = ? for update");//错误写法
        query.setLockOptions(LockOptions.UPGRADE);//添加写锁
        query.setParameter(0,1);
        System.out.println(query.uniqueResult());
        //提交事务
        session.getTransaction().commit();
        session.close();
  • 效果相同
    在这里插入图片描述
  • 注意不能使用update添加写锁,报错。
    在这里插入图片描述

总结: 一个线程开启事务给一个表或一行数据添加写锁,该线程可以对这个表或一行记录进行查询更新等操作,直到该线程提交事务,别的线程不能给这个表添加写锁和更新数据,可以查询(看)到加锁的表或记录。
在这里插入图片描述

第二节 Hibernate乐观锁

  • 乐观锁就是在表中添加一个version字段来控制数据的不一致性
  • 在PO对象(javabean)提供version字段,表示版本字段,类型一般为Integer。
  1. 在Customer中添加version字段
    在这里插入图片描述
  2. 在Customer.hbm.xml中配置version
    在这里插入图片描述
  3. 注意version字段配置的位置,位置不对会报错(通过查看dtd约束知道要配置在id后property前)
    在这里插入图片描述
  4. 配置完成后试运行,让表添加上对应的version字段。
    在这里插入图片描述
  • 默认的版本号为0
    在这里插入图片描述
  1. 乐观锁,每次更新,数据不同,版本号才会加1(get有session缓存与快照对比,只有不同才会更新到数据库),否则版本号不变。
	//乐观锁
    @Test
    public void test4(){
   
        Session session = HibernateUtils.openSession();
        session.beginTransaction();
        Customer customer = (Customer) session.get(Customer.class, 1);
        customer.setCustomerName("shu");//更新id为1的客户名
        System.out.println(customer);
        session.getTransaction().commit();
        session.close();
    }

在这里插入图片描述
在这里插入图片描述
6. 如果当前版本【1】比数据库版本【2】低就不更新,抛出异常

  • 断点调试获取此时数据库版本号version为1
    在这里插入图片描述

  • 如果有一个线程在此时更新了数据库字段,版本号加1,为2
    在这里插入图片描述

  • 继续执行程序就会抛出异常,这一行已经被另一个事务更新或删除【版本低,保存不成功】
    在这里插入图片描述

总结:
写锁是mysql数据库内部实现的,前后台都可以使用,使用时保证数据访问的安全性,即谁先访问加写锁,别的线程无法操作,要等待它结束(事务提交)才能访问操作。
乐观锁是hibernate通过对表添加一个字段version来实现的,通过更新时版本号的增加保证数据的安全。

第三节 Hibernate整合log4j

3.1 Log4j是什么?【java日志】

  • Log4j的主要功能是在控制台输出固定格式的日志,并能把日志写在文件中,方便项目上线后的系统维护。

3.2 整合步骤

第一步:导入以下2个jar包

在这里插入图片描述
在这里插入图片描述

slf4j-log4j12-1.7.2.jar是桥接左右2个jar包作用(桥梁互通)
在这里插入图片描述

第二步:把下图的log4j.properties文件导入项目的src目录中

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值