HQL、QBC详解、c3p0连接池的整合、事务的隔离级别、乐观锁、悲观锁
一、HQL详解:
①关于HQL的使用语法:[select/update/delete...][from...][类名 as 别名][where...][group by...][having...][order by...][asc/desc]
②关于HQL的介绍:(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语句有些相似,但它使用的是类、对象和属性的概念,而没有表和字段的概念。HQL是hibernate官方推荐的查询语句,也是使用最广泛的一种检索方式,当检索数据表中所有记录时,查询语句中可以省略select关键字。例如:from Customer==>表示查询整个Customer持久类对应的表记录。
③HQL常用操作展示:
/**
* HQL查询详解
* HQL查询表中的所有数据
*
*/
@Test
public void fun01(){
Session session=HibernateUtils.openSession();
Transaction transaction=session.beginTransaction();
//-------------------------------------------------
//使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
Query query= session.createQuery("from Customer");
List<Customer> list=query.list();
System.out.println(list);
//-------------------------------------------------
transaction.commit();
session.close();
}
/**
* HQL语句详解
* 查询指定条件的数据使用where关键字来查询
*/
@Test
public void fun02(){
Session session=HibernateUtils.openSession();
Transaction transaction=session.beginTransaction();
//-------------------------------------------------
//查询指定的数据
Query query = session.createQuery("select c from Customer as c where id=1 ");
Customer c=(Customer) query.uniqueResult();
System.out.println(c);
//-------------------------------------------------
transaction.commit();
session.close();
}
投影查询返回的是一个对象数组,不再是封装到对象里
/**投影查询:只查询出部分数据,list()方法返回的将会是一个对象数组
* HQL查询详解
* HQL查询表中的所有数据
*
*/
@Test
public void fun03(){
Session session=HibernateUtils.openSession();
Transaction transaction=session.beginTransaction();
//-------------------------------------------------
//使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
Query query = session.createQuery("select c.id,c.name from Customer as c ");
List<Object[]> list=query.list();//返回的是一个数组需要用数组对象数组作为泛型
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
动态实例查询:也就是将投影查询的对象数组封装到对象中,注意需要提供相应的构造函数
//对应着HQL语句的构造函数的写法
public Customer(Integer id, String name) { super(); this.id = id; this.name = name; }
/**动态实例查询
* HQL语句详解
* 用HQL查询某几个指定的元素,执行list()返回的不再是一个对象而是数组里面装着对象的数据
* 想要将数据在查询时就封装到对象里面需要使用语法
* 使用HQL语句查询语法:[select] new Customer(类(类别名).成员变量名称)from 类名 [as] 别名 [where]...
* 切记使用这样的语法需要在对应的类里面添加相应的构造函数
*/
@Test
public void fun04(){
Session session=HibernateUtils.openSession();
Transaction transaction=session.beginTransaction();
//-------------------------------------------------
//将数据在查询时就封装的类对象里面去(前提要提供相应的构造函数)
Query query = session.createQuery("select new Customer(c.id,c.name) from Customer as c ");
List<Customer> list=query.list();
System.out.println(list);
//-------------------------------------------------
transaction.commit();
session.close();
}
1 /**
2 * HQL语句详解
3 * HQL语句排序查询 使用关键字order by [asc(升序)|desc(降序)]
4 */
5 @Test
6 public void fun05(){
7
8 Session session=HibernateUtils.openSession();
9 Transaction transaction=session.beginTransaction();
10 //-------------------------------------------------
11 //排序查询
12 Query query = session.createQuery("select c from Customer as c order by id asc");
13 List<Customer> list=query.list();
14 for (Customer customer : list) {
15 System.out.println(customer.getId());
16 }
17
18
19 //-------------------------------------------------
20 transaction.commit();
21 session.close();
22
23 }
/**
* HQL语句详解
* HQL语句分页查询 具体的分页公式可以查询javaweb第20天的练习
*/
@Test
public void fun06(){
Session session=HibernateUtils.openSession();
Transaction transaction=session.beginTransaction();
//-------------------------------------------------
//分页查询
Query query = session.createQuery("select c from Customer as c");
query.setFirstResult(1);//设置其实数据的位置index=当前数据位数-1
query.setMaxResults(2);//设置最大查询几条数据
List<Customer> list=query.list();
for (Customer customer : list) {
System.out.println(customer);
}
//-------------------------------------------------
transaction.commit();
session.close();
}
1 /**
2 * HQL语句详解
3 * HQL语句绑定参数查询
4 * 有两种绑定参数的方式第一种 ...where id=? 第二种...where id=:haha
5 */
6 @Test
7 public void fun07(){
8
9 Session session=HibernateUtils.openSession();
10 Transaction transaction=session.beginTransaction();
11 //-------------------------------------------------
12 //分页查询
13 //Query query = session.createQuery("select c from Customer as c where id=?");
14 // query.setInteger(0,1);//这里的参数占位符索引位置从零开始
15
16 Query query = session.createQuery("select c from Customer as c where id=:haha");
17 query.setInteger("haha", 2);//这里注入参数时使用别名来指定注入的位置
18
19 List<Customer> list=query.list();
20 for (Customer customer : list) {
21 System.out.println(customer);
22 }
23
24
25 //-------------------------------------------------
26 transaction.commit();
27 session.close();
28
29 }
1 /**
2 * HQL语句详解
3 * HQL语句聚合函数查询
4 */
5 @Test
6 public void fun08(){
7
8 Session session=HibernateUtils.openSession();
9 Transaction transaction=session.beginTransaction();
10 //-------------------------------------------------
11
12
13
14 // 第一种方式 *
15 // Query query = session.createQuery("select count(*) from Customer c");
16 // 第二种方式 别名
17 // Query query = session.createQuery("select count(c) from Customer c");
18 // 第三种方式 oid
19 // Query query = session.createQuery("select count(c.id) from Customer c");
20
21 Query query = session.createQuery("select count(c.id) from Customer as c ");
22
23
24 Long num=(Long) query.uniqueResult();
25 int intvalue=num.intValue();
26
27 System.out.println(intvalue);
28 //-------------------------------------------------
29 transaction.commit();
30 session.close();
31
32 }
1 /**
2 * HQL语句详解
3 * HQL语句分组group by ...having...查询
4 */
5 @Test
6 public void fun09(){
7
8 Session session=HibernateUtils.openSession();
9 Transaction transaction=session.beginTransaction();
10 //-------------------------------------------------
11
12 Query query = session.createQuery("select o.customer, count(o) from Order as o group by o.customer having count(o)>1 ");
13 List<Object[]> list=query.list();
14
15 for (Object[] objects : list) {
16 System.out.println(Arrays.toString(objects));
17 }
18 //-------------------------------------------------
19 transaction.commit();
20 session.close();
21
22 }
23 }
④HQL的表连接查询:
表连接查询的分类:
HQL语句的表连接查询
交叉查询==>笛卡尔积
内连接 : 隐式内连接==》在笛卡尔积上过滤掉无效数据,显示内连接(迫切|非迫切)==》inner join ... on
外连接: 左外连接(迫切|非迫切),右外连接(迫切|非迫切)
a.交叉查询会产生大量的无用代码,也就是会出现笛卡尔积。
1 /**
2 * HQL语句的表连接查询
3 * 交叉查询==>笛卡尔积
4 * 内连接 :
5 * 隐式内连接==》在笛卡尔积上过滤掉无效数据
6 * 显示内连接(迫切|非迫切)==》inner join ... on
7 * 左外连接
8 * 右外连接
9 */
10 @Test//交叉查询==>笛卡尔积
11 public void fun01(){
12 Session session=HibernateUtils.openSession();
13 Transaction transaction=session.beginTransaction();
14 //-------------------------------------------------
15 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
16 Query query= session.createQuery("from Customer c,Order o");
17 List<Object[]> list=query.list();
18 for (Object[] objects : list) {
19 System.out.println(Arrays.toString(objects));
20
21 }
22
23 //-------------------------------------------------
24 transaction.commit();
25 session.close();
26
27 }
b.隐式内连接用来过滤掉无用代码,去除笛卡尔积
1 @Test//隐式内连接==>笛卡尔积
2 public void fun02(){
3 Session session=HibernateUtils.openSession();
4 Transaction transaction=session.beginTransaction();
5 //-------------------------------------------------
6 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
7 Query query= session.createQuery("from Customer c,Order o where o.customer=c");
8 List<Object[]> list=query.list();
9 for (Object[] objects : list) {
10 System.out.println(Arrays.toString(objects));
11
12 }
13
14 //-------------------------------------------------
15 transaction.commit();
16 session.close();
17
18 }
c.显示内连接,非迫切调用list()方法,返回的是List<Object[]> list=....可以看出返回的是一个对象数组的集合,Object[] 数组中的值为{Customer ,Order }。
1 @Test//显示内连接==>(非迫切)inner join
2 //List<Object[]>
3 //Object[]=>[Customer,Order]
4 //将一方与多方对象装入数组中分 别返回
5 public void fun03(){
6 Session session=HibernateUtils.openSession();
7 Transaction transaction=session.beginTransaction();
8 //-------------------------------------------------
9 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
10 Query query= session.createQuery("from Customer c inner join c.orders ");
11 List<Object[]> list=query.list();
12 for (Object[] objects : list) {
13 System.out.println(Arrays.toString(objects));
14
15 }
16
17 //-------------------------------------------------
18 transaction.commit();
19 session.close();
20
21 }
d.显示内连接,迫切调用list()方法,返回的是List<Customer> list=...可以看出返回的是一个对象集合,Customer对象里面包含着Order对象。
1
2 @Test//显示内连接==>(迫切)inner join
3 //List<Customer>
4 //迫切连接会将多方的装入一方,组装成对象返回
5
6 public void fun04(){
7 Session session=HibernateUtils.openSession();
8 Transaction transaction=session.beginTransaction();
9 //-------------------------------------------------
10 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
11 Query query= session.createQuery("from Customer c inner join fetch c.orders ");
12 List<Customer> list=query.list();
13 for (Customer c : list) {
14 System.out.println(c);
15
16 }
17
18 //-------------------------------------------------
19 transaction.commit();
20 session.close();
21
22 }
1 @Test//左外连接连接(非迫切)==>left outer join
2 public void fun05(){
3 Session session=HibernateUtils.openSession();
4 Transaction transaction=session.beginTransaction();
5 //-------------------------------------------------
6 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
7 Query query= session.createQuery("from Customer c left outer join c.orders ");
8 List<Object[]> list=query.list();
9 for (Object[] objs : list) {
10 System.out.println(Arrays.toString(objs));
11
12 }
13 //-------------------------------------------------
14 transaction.commit();
15 session.close();
16
17 }
1 @Test//左外连接连接(迫切)==>left outer join fetch
2
3 public void fun06(){
4 Session session=HibernateUtils.openSession();
5 Transaction transaction=session.beginTransaction();
6 //-------------------------------------------------
7 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
8 Query query= session.createQuery("from Customer c left outer join fetch c.orders ");
9 List<Customer> list=query.list();
10 for (Customer c : list) {
11 System.out.println(c);
12
13 }
14
15 //-------------------------------------------------
16 transaction.commit();
17 session.close();
18
19 }
1 @Test//右外外连接连接(非迫切)==>right outer join
2 public void fun07(){
3 Session session=HibernateUtils.openSession();
4 Transaction transaction=session.beginTransaction();
5 //-------------------------------------------------
6 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
7 Query query= session.createQuery("from Customer c right outer join c.orders ");
8 List<Object[]> list=query.list();
9 for (Object[] o: list) {
10 System.out.println(Arrays.toString(o));
11
12 }
13
14 //-------------------------------------------------
15 transaction.commit();
16 session.close();
17
18 }
1 @Test//右外外连接连接(迫切)==>left outer join fetch
2
3 public void fun08(){
4 Session session=HibernateUtils.openSession();
5 Transaction transaction=session.beginTransaction();
6 //-------------------------------------------------
7 //使用HQL语句查询语法:[select][类(类别名).成员变量名称]from 类名 [as] 别名 [where]...
8 Query query= session.createQuery("from Customer c right outer join fetch c.orders ");
9 List<Customer> list=query.list();
10 for (Customer c : list) {
11 System.out.println(c);
12
13 }
14
15 //-------------------------------------------------
16 transaction.commit();
17 session.close();
18
19 }
20 }
⑤HQL的命名查询:
局部配置,需要在ORM映射文件中配置在class元素里面配置
<class>
<!-- 命名查询的查询语句需要用CDATA区包裹 (局部配置) 在class里面配置为局部的-->
<query name="abc"><![CDATA[from Order]]></query>
</class>
1 @Test//HQL的命名查询
2 //找到局部的配置的HQL语句
3 //<!-- 命名查询的查询语句需要用CDATA区包裹 (局部配置)-->
4 //<query name="abc"><![CDATA[from Order]]></query>
5 //</class>在class里面配置为局部的
6 public void fun01(){
7 Session session=HibernateUtils.openSession();
8 Transaction transaction=session.beginTransaction();
9 //-------------------------------------------------
10 //这里我们需要使用getNamedQuery方法来使用命名查询,参数为javabean全类名.命名函数:cn.itcast.a.domain.Customer.bcd,
11 Query query= session.getNamedQuery("cn.itcast.a.domain.Customer.bcd");
12 List<Order> list=query.list();
13
14 for (Order o : list) {
15 System.out.println(o);
16
17 }
18
19 //-------------------------------------------------
20 transaction.commit();
21 session.close();
22
23 }
全局配置,需要在ORM映射文件中配置在class元素外面,在hibernate-mapping里面配置
<!-- 命名查询的查询语句需要用CDATA区包裹 (全局配置),在class外面的为全局配置-->
</hibernate-mapping>
<query name="abc"><![CDATA[from Customer]]></query>
</hibernate-mapping>
1 @Test//HQL的命名查询
2 //找到全局配置的HQL语句
3 // <!-- 命名查询的查询语句需要用CDATA区包裹 (全局配置)-->
4 // <query name="abc"><![CDATA[from Customer]]></query>
5 //</hibernate-mapping> 在class外面的为全局配置
6 public void fun02(){
7 Session session=HibernateUtils.openSession();
8 Transaction transaction=session.beginTransaction();
9 //-------------------------------------------------
10 //找全局 的HQL语句,这里我们需要使用getNamedQuery方法来使用命名查询,参数为abc,与局部相比是不用写完整的类名了
11 Query query= session.getNamedQuery("abc");
12 List<Customer> list=query.list();
13
14 for (Customer c : list) {
15 System.out.println(c);
16
17 }
18
19 //-------------------------------------------------
20 transaction.commit();
21 session.close();
22
23 }
24
25 }
二、QBC查询详解 :
1.QBC介绍:QBC是一种无语句的检索方式,是Hibernate提供的另一种检索对象的方式,它主要是由Criteria接口、Criterion接口、和Express类组成。并且还提供了add(Criterion criterion)方法来添加查询的条件。
2.QBC的其他查询介绍:
a.QBC的分页查询和HQL语句类似
1 @Test//QBC的分页查询
2 public void fun01(){
3 Session session=HibernateUtils.openSession();
4 Transaction transaction=session.beginTransaction();
5 //-------------------------------------------------
6 Criteria criteria = session.createCriteria(Customer.class);
7 criteria.setFirstResult(0);//设置起始的查询位置
8 criteria.setMaxResults(3);//设置查询多少个
9 List<Customer> list=criteria.list();
10
11 for (Customer c : list) {
12 System.out.println(c);
13
14 }
15
16 //-------------------------------------------------
17 transaction.commit();
18 session.close();
19
20 }
b.QBC多条件查询
需要多次调用add(Criterion cricriterion)方法,我们通常会传入 Restrictions类的一些静态方法返回Criterion接口的实例
常用的静态方法有:eq(String s,Object o) 表示相等= gt(String s,Object o) 表示大于> ge(String s,Object o) 表示大于等于>= lt(String s,Object o) 表示小于
le(String s,Object o) 表示小于等于<= like(String s,Object o) 表示对应着SQL语句中的like用作模糊查询等等,详情见ssh书的187页
1 @Test//QBC的多条件查询
2 public void fun02(){
3 Session session=HibernateUtils.openSession();
4 Transaction transaction=session.beginTransaction();
5 //-------------------------------------------------
6 Criteria criteria = session.createCriteria(Customer.class);
7 criteria.add(Restrictions.like("name", "%小%"));//模糊查询的条件
8 criteria.add(Restrictions.ge("id", 4));//id大于4的顾客
9 List<Customer> list=criteria.list();
10
11 for (Customer c : list) {
12 System.out.println(c);
13
14 }
15
16 //-------------------------------------------------
17 transaction.commit();
18 session.close();
19
20 }
c.QBC排序查询调用的是addOrder(Order.[asc|desc])方法来进行排序查询
1 @Test//QBC的排序查询
2 // criteria.addOrder(Order.asc("id"));按照id的升序排列
3 // criteria.addOrder(Order.desc("id"));按照id的降序排列
4 public void fun03(){
5 Session session=HibernateUtils.openSession();
6 Transaction transaction=session.beginTransaction();
7 //-------------------------------------------------
8 Criteria criteria = session.createCriteria(Customer.class);
9 criteria.addOrder(Order.asc("id"));
10 // criteria.addOrder(Order.desc("id"));
11
12 List<Customer> list=criteria.list();
13
14 for (Customer c : list) {
15 System.out.println(c);
16
17 }
18
19 //-------------------------------------------------
20 transaction.commit();
21 session.close();
22
23 }
d.QBC的离线查询:
什么是离线查询?一般的我们都是在Dao层拼装的查询条件因为service层不能碰与数据库相关的api
但是我们想要在service层里面拼装条件怎么办?
QBC提供离线查询时查询条件可以在service层拼装
1 @Test//QBC的离线查询
2 //什么是离线查询?一般的我们都是在Dao层拼装的查询条件因为service层不能碰与数据库相关的api
3 //但是我们想要在service层里面拼装条件怎么办
4 //QBC提供了离线查询可以在service层里面离线拼装数据不需要session
5 public void fun04(){
6 /****************模拟service层**********************/
7 DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Customer.class);
8 detachedCriteria.add(Restrictions.eq("id", 5));
9 //---------------------------------------------------
10 //模拟dao层
11 Session session=HibernateUtils.openSession();
12 Transaction transaction=session.beginTransaction();
13
14 //从service层中将detachedCriteria传递进来
15 //离线的Criteria绑定session
16 Criteria criteria=detachedCriteria.getExecutableCriteria(session);
17 Customer customer= (Customer) criteria.uniqueResult();//执行单行结果集
18 System.out.println(customer);
19 //-------------------------------------------------
20 transaction.commit();
21 session.close();
22
23 }
24
25 }
三、c3p0数据库连接池的整合:
1.前提我们需要在hibernate配置文件hibernate.cfg.xml打开整合c3p0的开关,关于配置可以在hibernate.properties里面查找,当我们打开了开关后,还可以配置连接池的参数,如果不配连接池参数就会默认使用默认参数
代码如下:
<!-- 想要整合c3p0连接池需要打开配置开关
hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 连接池参数的配置,如果不配也会有默认值
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
-->
<property name="hibernate.c3p0.max_size">2</property>
<property name="hibernate.c3p0.min_size">2</property>
2.配置完成后我们创建一个测试类打印session:
1 public class Demo01 {
2
3 @Test//整合c3p0的演示代码
4 public void fun01(){
5 //开启一个session
6 Session session=HibernateUtils.openSession();
7 Transaction transaction=session.beginTransaction();
8 //------------------------------------------------
9 System.out.println(session);
10 //------------------------------------------------
11 transaction.commit();
12 session.close();
13 }
14 }
控制台会打印出这样的信息说明整合成功了:
四、在hibernate中配置事务的隔离级别:
1.关于自动提交事务需要在hibernate配置文件中配置:
<!--设置制动提交事务 的配置信息 ,会自动判断你事务的起点和终点,但是在实际开发中是不会自动提交事务的
<property name="hibernate.connection.autocommit">true</property>
-->
2.我们需要在hibernate配置文件中配置事务的隔离级别:每个隔离级别的值对应着数据库中的隔离级别
<property name="hibernate.connection.isolation">4</property>
hibernate连接数据库中事务配置事务的隔离级别:取值为
0:表示没有隔离级别
1:读操作未提交
2:读操作已提交
4:可重复读
8 :可串行化
五、悲观锁和乐观锁
1.锁的介绍:
数据库中的锁
数据库的锁(了解的了解)
①悲观锁(数据库提供实现) . 默认认为一定会发送别人要修改我使用的数据. 那我就可以为我读取的数据加锁.
a.读锁/共享锁 => 读锁可被其他线程所共享,如果是读取的话大家都可以用这把锁读到数据.
select * from table lock in share mode(读锁、共享锁)当一个人持有锁时数据还是能被修改只有两个人以上的持有这个锁则不能修改
当事务提交时锁就会被释放。
在数据库中的读写锁操作演示:
START TRANSACTION;
SELECT * FROM t_customer LOCK IN SHARE MODE; #读锁(共享锁)
SELECT * FROM t_customer FOR UPDATE;#写锁(排它锁)
UPDATE t_customer SET NAME='刘小君' WHERE id=1;
COMMIT;
当两方同时开启事务同时加上读锁时则不能修改数据否则会出现如下的状态:当执行修改语句时状态栏一直在转显示不出成功信息,此时的状态是不能修改数据的
b.写锁/排他锁 => 写锁不能共享,只要有人为数据加入了写锁,其他人就不能为数据加任何锁.
select * from table for update (写锁、排它锁)
当两方同时开启事务同时,写锁只能被一方加上只有等这一方操作完成释放了写锁后,才能在另一方加上写锁:当被加上写锁的事务可以操作数据库,而别人是不能加写锁的只有等事务提交后另一方才能操作写锁不然控制台不会显示成功信息的,而且查询的语句一直在等待。如图:
我们在数据库中操作读写锁如何在hibernate中操作呢?(代码如下)
1 @Test//悲观锁如何在hibernate中添加
2 //读锁演示
3 public void fun01(){
4 //开启一个session
5 Session session=HibernateUtils.openSession();
6 Transaction transaction=session.beginTransaction();
7 //------------------------------------------------
8 //使用get查询方法中含有三个参数的使用LockOptions.UPGRADE添加读锁
9 Customer customer =(Customer) session.get(Customer.class, 1, LockOptions.READ);
10
11 System.out.println(customer);
12 //------------------------------------------------
13 transaction.commit();
14 session.close();
15 }
1 @Test//悲观锁如何在hibernate中添加
2 //写锁演示
3 public void fun02(){
4 //开启一个session
5 Session session=HibernateUtils.openSession();
6 Transaction transaction=session.beginTransaction();
7 //------------------------------------------------
8 //使用get查询方法中含有三个参数的使用LockOptions.UPGRADE添加读锁
9 Customer customer =(Customer) session.get(Customer.class, 1, LockOptions.UPGRADE);
10
11 System.out.println(customer);
12 //------------------------------------------------
13 transaction.commit();
14 session.close();
15 }
16
17 }
②乐观锁(需要自己实现):乐观锁就是什么锁都不加,任何人都可以操作数据,但是会在表中添加一列version的字段,这个version的字段表示为版本号,执行修改操作时会在version列的int数值上+1。
如果同时开启两个操作其中有一个操作在前面提交了数据修改了版本号,另一个的版本号正好和此时数属记录的版本号相同那么就会报错
修改后的版本号需要比数据记录的版本号多1个:也就是 修改后的版本号=之前的版本号+1才能正常执行操作。
乐观锁在hibernate中的实现:
Ⅰ.需要在想要操作的表对应的ORM映射文件中加入
<!-- 告述hibernate,乐观锁的版本号属性名 ,然后hibernate会自动帮我们添加这个锁-->
<version name="version"></version>
Ⅱ.在hibernate中正常操作即可每次操作他都会在原有版本号上+1
1 import org.hibernate.Transaction;
2 import org.hibernate.classic.Session;
3 import org.junit.Test;
4
5 import cn.itcast.Hibernate.utils.HibernateUtils;
6 import cn.itcast.a.domain.Customer;
7
8 public class Demo02 {
9 @Test//测试乐观锁的操作
10 public void fun01(){
11 //开启一个session
12 Session session=HibernateUtils.openSession();
13 Transaction transaction=session.beginTransaction();
14 //------------------------------------------------
15
16 Customer customer =(Customer) session.get(Customer.class, 1);
17 //当我们修改数据时我们这个时候将数据放到了缓存中当提交事务时将会比对版本号,然后版本号如果不是(当前版本号-1)则会报错
18 customer.setName("刘小君");
19
20 System.out.println(customer);
21 //------------------------------------------------
22 transaction.commit();
23 session.close();
24 }
25 }
Ⅲ.如果修改后的版本号和数据库中的版本号相同锁明有人在你前面修改了这条数据则会报错