演示hibernate如何产生丢失更新的
丢失更新是怎么玩的?首先两个事务先都把它查出来。
A事务里面去修改的数据没了,被B事务覆盖掉了。这是被B事务提交覆盖,B事务回滚也能覆盖。这就是丢失更新的效果。
悲观锁使用了数据库的锁机制,
这就是悲观锁的解决方案,但是这种方式并不是特别的好。因为这条记录被锁定了,其他人都不能操作这条记录了。必须等排它锁被释放完其他人才能操作,这是悲观锁来解决。
乐观锁来解决。
这是关于session的一些本地操作,一会我们来说它。
乐观锁是怎么做的?相当于在我们这里加了一个版本号。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.itcast.vo"><!-- 如果这里配置了包名下面可以不用写 --> <!-- <hibernate-mapping> --> <!-- <class name="cn.itcast.hibernate3.demo2.Customer" table="customer"> --> <!-- <class name="cn.itcast.vo.Customer" table="customer"> --> <class name="Customer" batch-size="2" table="customer"> <!-- 配置唯一标识 --> <id name="cid" column="cid"> <generator class="native"/> </id> <!-- version标签是版本号 --> <version name="version"></version> <!-- 配置普通属性 --> <property name="cname" column="cname" length="30"/> <property name="age" column="age" length="30"/> <!-- 建立映射 --> <!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. --> <!-- 这里把级联去掉 要最简短的配置 <set name="orders" cascade="save-update" inverse="true"> --> <set name="orders" cascade="save-update" batch-size="2"> <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. --> <key column="cno"></key> <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 --> <!-- <one-to-many class="cn.itcast.hibernate3.demo2.Order"/> --> <one-to-many class="cn.itcast.vo.Order"/> </set> </class> <!-- 命名查询的方式 --> <query name="findAll"> from Customer </query> <!-- 这里要写sql语句 <sql-query> </sql-query> --> </hibernate-mapping>
package cn.itcast.test; import org.hibernate.LockMode; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import cn.itcast.utils.HibernateUtils; import cn.itcast.vo.Customer; /** * * Hibernate的事务管理: * @author zhongzh * */ public class HibernateDemo3 { @Test /* * 使用乐观锁解决丢失更新 也需要两个事务同时操作这条记录。 */ public void demo6(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 3); customer.setAge(26); tx.commit(); session.close(); } @Test /* * 使用乐观锁解决丢失更新 */ public void demo5(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 3); customer.setCname("沈明贞"); tx.commit(); session.close(); } @Test /* * 使用悲观锁解决丢失更新 底层执行的是同一个,只不过事务不一样而已 */ public void demo4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 使用悲观锁(排它锁) @SuppressWarnings("deprecation") Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE); customer.setAge(32); tx.commit(); session.close(); } @Test /* * 使用悲观锁解决丢失更新 */ public void demo3(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 使用悲观锁(排它锁) @SuppressWarnings("deprecation") Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE); customer.setCname("沈明贞"); tx.commit(); session.close(); } @Test /* * * 丢失更新的产生 * */ public void demo2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 3); //再有一个事务去更新customer的年龄 customer.setAge(30);//持久态对象不用手动调update都可以完成更新 //System.out.println(customer); tx.commit(); session.close(); } @Test /* * * 丢失更新的产生 * */ public void demo1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 3); //假设就有一个事务在更新这个customer的名称 customer.setCname("沈明贞"); //System.out.println(customer); tx.commit(); session.close(); } }