上篇文章具体讨论了hql的各种查询方法。在讨论过程中写了代码演示样例。hql的查询方法类似于sql,查询的方法比較简单,有sql基础的开发者在使用hql时就会变得相当的简单。
Hibernate在操作数据库的同一时候也提供了对数据库操作的限制方法。这样的方法被称为锁机制,Hibernate提供的锁分为两种一种是乐观锁。第二种是悲观锁。
通过使用锁可以控制数据库的并发性操作。限制用户对数据库的并发性的操作。
锁能控制数据库的并发操作,通过使用锁来控制数据库的并发操作,Hibernate提供了两种锁来控制数据库的操作,各自是乐观锁和悲观锁。
乐观锁:大多数是採用数据版本号的方式实现,一般在数据库中增加一个version字段,在读取数据的时候将version取出来,在保存数据的时候推断version的值是否小于数据库中的version值,假设小于不会更新,否则可更新数据库。
悲观锁:一般是由数据库机制实现的,在整个过程中把数据锁住(查询时)。仅仅要事务不释放(提交/回滚)那么不论什么用户都不能查看和改动,通过使用LockMode来控制对数据库的操作。
乐观锁是通过在数据库中加入一个名为version的字段来实现每次对数据的校验,在每次操作数据库的时候会自己主动更新version的值,这样每次操作的version值是不一样的,所以假设有并发操作时将会首先校验version值是否小于数据库的version值。假设小于的话不会更新数据库,它的详细用法例如以下演示样例:
该类是映射的实体类,当中的属性quantity是数字的个数,在以下演示的演示样例中通过操作quantity来更新数据库的信息,另外的version字段是数据库信息的版本。能通过校验来实现控制数据库的操作,它的详细控制方法要在映射文件里编写实现。
package com.src.hibernate;
public class Inventory {
//主键id,标识号
private String itemNo;
public String getItemNo() {
return itemNo;
}
public void setItemNo(String itemNo) {
this.itemNo = itemNo;
}
//列表名称
private String itemName;
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
//个数
private int quantity;
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
//版本
private int version;
public int getVersion() {
return version;
}
public void setVersion(int version) {
this.version = version;
}
}
在映射文件里须要加入<version>字段来实现对数据库版本的映射,该标签的name属性要设置为相应实体中的version字段,这样在操作数据库时它会自己主动校验数据库版本来限制对数据的操作。
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.src.hibernate.Inventory" table="t_inventory"> <id name="itemNo"> <generator class="assigned"/> </id> <version name="version"/> <property name="itemName" type="string"/> <property name="quantity" type="integer"/> </class> </hibernate-mapping>
測试上面的演示样例,在程序中加入了两个方法来载入并改动数据,当中的testLoad1()方法首先载入数据库中的数据,并改动字段Quantity的值。改动后保存数据,这时要设置断点,在提交事务时设置断点,停止对数据库的提交操作。此时运行testLoad2()方法,将会发出错误信息,不能更新数据库操作。
public void testLoad1(){
Session session=null;
try{
//创建session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
Inventory inven=(Inventory)session.load(Inventory.class, "1001");
System.out.println("p1-->name:"+inven.getItemName());
inven.setQuantity(inven.getQuantity()-200);
session.save(inven);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testLoad2(){
Session session=null;
try{
//创建session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
Inventory inven=(Inventory)session.load(Inventory.class, "1001");
System.out.println("p2-->name:"+inven.getItemName());
inven.setQuantity(inven.getQuantity()-200);
session.save(inven);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}Hibernate: select inventory0_.itemNo as itemNo0_0_, inventory0_.version as version0_0_, inventory0_.itemName as itemName0_0_, inventory0_.quantity as quantity0_0_ from t_inventory inventory0_ where inventory0_.itemNo=? p2-->name:zhangsan Hibernate: update t_inventory set version=?, itemName=?, quantity=?where itemNo=? and version=?
悲观锁和乐观锁不同。它是通过数据库机制限制对数据库的操作的,通过用法的LockMode參数来配置对数据库的并发操作。在一次訪问过程中将会把数据锁住(查询时),仅仅要事务不提交那么不论什么用户都不能查看和改动,其他用户操作时将会被堵塞。不能同一时候操作,须要等待第一次訪问完毕后再进行其他的操作。详细方法例如以下演示样例。
实体内容和乐观锁同样,不同的是在实体中不须要加入版本属性,由于它不是通过推断版本来限制操作的。
package com.src.hibernate;
public class Inventory {
//主键id,标识号
private String itemNo;
public String getItemNo() {
return itemNo;
}
public void setItemNo(String itemNo) {
this.itemNo = itemNo;
}
//列表名称
private String itemName;
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
//个数
private int quantity;
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
实体相应的映射文件也相当的简单,仅仅须要配置相应的映射就可以,没有其他复杂的操作。例如以下代码:
<?xml version="1.0"?
> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.src.hibernate.Inventory" table="t_inventory"> <id name="itemNo"> <generator class="assigned"/> </id> <property name="itemName" type="string"/> <property name="quantity" type="integer"/> </class> </hibernate-mapping>
这里採用两个方法来測试操作,当中的testLoad1()方法首先查询数据然后改动数据,testLoad2()也是查询和改动数据,例如以下代码:
public void testLoad1(){
Session session=null;
try{
//创建session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
Inventory inven=(Inventory)session.load(Inventory.class, "1001",LockMode.UPGRADE);
System.out.println("p1-->name:"+inven.getItemName());
inven.setQuantity(inven.getQuantity()-200);
session.save(inven);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testLoad2(){
Session session=null;
try{
//创建session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
Inventory inven=(Inventory)session.load(Inventory.class, "1001",LockMode.UPGRADE);
System.out.println("p2-->name:"+inven.getItemName());
inven.setQuantity(inven.getQuantity()-200);
session.save(inven);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
Hibernate的锁机制限制了数据库的并发性的操作,功能非常强大,在使用时建议使用悲观锁。由于悲观锁使用的是数据库的机制,限制彻底。并且能确保数据的完整性。在使用这两种锁时各有优缺点,大数据量建议採用乐观锁,它会直接提示错误,性能上会高于悲观锁,悲观锁会加大数据库的负担,大数据量的话easy出现故障。
原文:http://www.cnblogs.com/yxysuanfa/p/6783367.html