事务:事务就是逻辑上的一组操作,要么全都成功,要么全都失败!!!
事务特性
原子性:事务一组操作不可分割.
一致性:事务的执行前后,数据完整性要保持一致.
隔离性:一个事务在执行的过程中不应该受到其他事务的干扰.
持久性:一旦事务结束,数据就永久保存数据库.
如果不考虑事务的隔离性引发一些安全性问题:
5大类问题:3类读问题 2类写问题.
读问题:
脏读 :一个事务读到另一个事务未提交数据.
不可重复读 :一个事务读到另一个事务已经提交数据(update),导致查询结果不一致.
虚读 :一个事务读到另一个事务已经提交的数据(insert),导致查询结果不一致
避免三种读的问题(设置事务的隔离级别):
未提交读:以上三种读问题 都有可能发生.
已提交读:避免脏读,但是不可重复读和虚读有可能发生.
重复读:避免脏读和不可重复读,但是虚读是有可能发生.
串行的:可以避免以上三种读问题.
在Hibernate中设置事务的隔离级别
在核心配置文件中
<!-- 1—Read uncommitted isolation 2—Read committed isolation 4—Repeatable read isolation 8—Serializable isolation --> <property name="hibernate.connection.isolation">4</property>
写问题:丢失更新
解决
悲观锁:依赖于数据库机制,锁住当前数据,其它任何用户都不能读取或修改
@Test /* * 使用悲观锁解决丢失更新 */ public void demo4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 使用悲观锁(排他锁),LockMode.UPGRADE:利用数据库的for update字句加锁 Customer customer = (Customer) session.get(Customer.class, 3, LockMode.UPGRADE); customer.setAge(32); tx.commit(); session.close(); }
乐观锁:不作数据库层次上的锁定,为了维护正确的数据,乐观锁采用应用程序上的逻辑实现版本控制的方法(在数据库中加入一个VERSON栏记录,在读取数 据时连同版本号一同读取,并在更新数据时递增版本号,然后比对版本号与数据库中的版本号,如果大于数据库中的版本号则予以更新,否则就回报错误)
public class Customer { private Integer cid; private String cname; private Integer version; public Integer getVersion() { return version; } public void setVersion(Integer version) { this.version = version; } public Integer getCid() { return cid; } public void setCid(Integer cid) { this.cid = cid; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } }
<hibernate-mapping > <class name="cn.yzu.vo.Customer" batch-size="2" table="customer" lazy="true"> <id name="cid" column="cid"> <generator class="native"/> </id> <version name="version"/> <property name="cname" column="cname" length="30"/> </class> </hibernate-mapping>
线程绑定的session
在Hibernate.cfg.xml中配置一个:<property name="hibernate.current_session_context_class">thread</property>
使用SessionFactory中的getCurrentSession()方法
底层就是ThreadLocal
当前线程中的session不需要进行关闭,线程结束后自动关闭!!!