hibernate-6-事务初步了解

来源:互联网 发布:2013office软件下载 编辑:程序博客网 时间:2024/05/18 16:54

实体类:

package com.entity;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.Version;import org.hibernate.annotations.GenericGenerator;@Entity@Table(name="person")public class Person {private Integer id;private String name;private String password;private Integer version;@Id@GeneratedValue(generator="increment")@GenericGenerator(name="increment",strategy="increment")public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Column(name="name")public String getName() {return name;}public void setName(String name) {this.name = name;}@Column(name="password")public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Version@Column(name="version")public Integer getVersion() {return version;}public void setVersion(Integer version) {this.version = version;}}
测试:

package com.test;import java.util.List;import org.hibernate.Criteria;import org.hibernate.Query;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.hibernate.criterion.Restrictions;import org.hibernate.criterion.SimpleExpression;import org.junit.Test;import com.entity.Person;import com.util.GetHibernateSessionFactory;public class Test4 {public static void main(String[] args) {//test01();//test02();test03();}/** * hibernate事务配置: hibernate事务配置 使用本地事务property name="hibernate.curent_session_session_class"thread /property 使用全局事务property name="hibernate.current_session_context_class" /property 设置事务的隔离级别property name="hibernate.connection.isolation"2 /property本地事务与全局事务暂时的理解(实际情况下常用本地事务):本地事务只针对一个数据库的操作,全局事务是有应用服务器进行管理的事务,它需要JTA(JTA非常笨重),并且可以用于多个事务性资源(跨多个数据库)事务并发问题:1.脏读:一个事务读取到另一个事务未提交的的数据2.不可重读:一个事务对同一行数据读取两次,但却得到不相同的结果3.虚读/幻读:事务A在操作的过程中两次查询同一个结果,第二次查询结果与第一次查询的结果不相同(有事务B插入了新数据)4.更新丢失:就是下面的“并发访问数据的丢失”<ctrl+F>查看,除了这种情况,还有一种情况,两个事务同时操作同一个数据,A事务撤销时,把已经提交的B事务更新  的数据覆盖了。这对B事务来说造成了数据丢失.事务的隔离级别:1:读操作未提交:一个事务已经开始写数据,则另一个事务只允许读此行数据,不允许写数据2:读操作已提交:读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行4:可重复读:读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。8:序列化:事务职能一个接着一个的执行,不能并发执行 *  *//** * test01,test02,test03三个方法查看访问数据时数据丢失 * 操作: * 1.在test02()和test03()方法的93和101行分别加上断点,也就是在设值得地方加上断点 * 2.选中test02()右键Debug as-->jUnit Test运行到tx.commit();这一行 * 3.在Outline窗口中单击test3()方法,选中右键Debug as-->jUnit Test * 4.在左上角Debug中点击TestMy05.test03[JUnit]下的TestMy05.test03() line:110这一行,表示进入test03()这个方法的调试,运行到tx.commit(); * 5.点击TestMy05.test02[JUnit]下的TestMy05.test02 line:102这一行 点击Resume(F8),表示让test02()运行完毕 * 6.查看数据库表person可以看到第一条数据为:改name 123 * 7.点击TestMy05.test03[JUnit]下的TestMy05.test03() line:104这一行,点击Resume(F8),表示让test03()运行完毕 * 8.查看数据库,可以看到person的第一条数据变成: 曹大帅哥 改密码 * 结果-》并发访问数据的丢失 *  * 悲观锁: * 悲观锁是指每次在操作数据库的时候,总是悲观的认为会有其他的事务也会来操作同一数据,所以在数据操作的过程中,会把数据处于锁定的状态,在锁定的时间 * 内,其他的事务不能对数据进行存储等操作。 * 注:悲观锁一般是由数据库来实现 * Mysql数据库的悲观锁的设置方式:Person p1 = (Person) session.get(Person.class, 2,LockMode.UPGRADE); * 设置后,不能同时读取一条数据,所以根本就不能并行执行 * Oracle的悲观锁用LockMode.UPGRADE_NOWAIT *  *  * 乐观锁(通常认为许多事务同时操作同一个数据的情况很少发生,所以不做数据层次的锁定): * 在Person类中添加字段private Integer version 并且生成get/set方法 * 在xml文件的配置中按如下配置 * <class name="com.entity.Person" table="person">  *<id name="id" column="id"> *<generator class="native"></generator> *</id> *<!-- version属性与数据库中的version属性字段映射 注意下面字段必须放在id标签之下 否则报错--> *<version name="version" column="version" type="integer" /> *<property name="name" column="name" type="string"></property> *<property name="password" column="password" type="string"></property> *</class> * 在按照上面的操作的调试方法,version会比原来加1,修改name字段的值,但是age字段的值不会修改,并且会报下面的错误 * org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.entity.Person#3] * 上述变化过程: * 运行test01()后version都是默认值为0 * test02()调试获取到的version是0运行到tx.commit();//此时还未提交 * test03()调试获取到的version也是0运行tx.commit(); * 此时释放test02()运行完所有的程序,提交事务,因为0 = 0 ,不小于, 所以更新数据,version+1 = 1 * 释放test03()运行完所有的程序,提交事务,因为0 < 1,所以禁止更新. *  * 乐观锁的运行机制: * 在读取数据的时候,将版本号一起读取出来,之后更新数据之前,将读取出来的版本号与数据中的版本号对比,只要不小于数据库中的版本号,就更新. */public static void test01(){Session session = GetHibernateSessionFactory.sessionFactory.openSession();Transaction t = session.beginTransaction();Person p = new Person();p.setName("曹大帅哥");p.setPassword("123");Person p2 = new Person();p2.setName("曹asdf帅哥");p2.setPassword("1sad3");Person p3 = new Person();p3.setName("safd帅哥");p3.setPassword("aaaaaaa");session.save(p);session.save(p2);session.save(p3);t.commit();session.close();GetHibernateSessionFactory.sessionFactory.close();}public static  void test02(){Session session = GetHibernateSessionFactory.sessionFactory.openSession();Transaction t = session.beginTransaction();//Person p1 = (Person) session.get(Person.class, 2,LockMode.UPGRADE);Person p1 = (Person) session.get(Person.class, 2);p1.setName("改name");session.update(p1);t.commit();session.close();GetHibernateSessionFactory.sessionFactory.close();}public static void test03(){Session session = GetHibernateSessionFactory.sessionFactory.openSession();Transaction t = session.beginTransaction();//Person p2 = (Person) session.get(Person.class, 2,LockMode.UPGRADE);Person p2 = (Person) session.get(Person.class, 2);p2.setPassword("改密码");session.update(p2);t.commit();session.close();GetHibernateSessionFactory.sessionFactory.close();}}



原创粉丝点击