JavaWeb学习之Hibernate框架(三)
hibernate中实体的规则
实体类创建的注意事项
1、持久化类提供无参构造
2、成员变量私有,需要提供属性(get/set方法)访问
3、持久化类中的属性,应尽量使用包装类(可以比基本数据类型多存一个null值)
4、持久化类需要提供oid,与数据库中的主键列对应(oid不是本表中的字段,只为传值使用)
5、不要用final修饰class---hibernate使用cglib代理生成代理对象,代理对象是继承被代理对象,如果被final修饰,将无法生成代理。
主键类型
自然主键(少见)---表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用。
代理主键(常见)---表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为主键。
主键生成策略
代理主键:identity:主键自增,由数据库来维护主键值,录入时不需要指定主键
sequence:Oracle中的主键生成策略
native:hilo+sequence+identity 自动三选一策略
uuid:产生随机字符串作为主键,主键类型必须为string 类型
自然主键:assigned:自然主键生成策略。hibernate不会管理主键值,由开发人员自己录入

hibernate中的对象状态
对象分为三种状态
瞬时状态:没有id,没有在session缓存中
持久化状态:有id,在session缓存中
游离/托管状态:有id,没有在session缓存中
三种状态的转换图

package com.test;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.domain.Customer;
import com.util.HibernateUtil;
public class Test01 {
@Test
//save方法实际作用:其实不能理解为保存,理解成将瞬时状态或者游离状态--->持久化状态
//sql实际上是为了生成主键id,将对象转为持久化状态,必须有id值(数据库中的id)
public void method1() {
// 获取会话对象
Session session = HibernateUtil.openSession();
// 开启事务
Transaction tx = session.beginTransaction();
Customer c = new Customer(); //瞬时状态(没有id,与session没有关联)
//c.setCust_id("1");//瞬时状态(id是数据库里面的id)
c.setCust_name("张三");//瞬时托管状态
session.save(c);//持久化状态(有id,与session有关联)
//insert只是为了生成id
tx.commit();
session.close();
}
}
@Test
//持久化状态的特点:持久化状态的对象的任何变化都会自动同步到数据库中
//update方法真正作用是:将游离状态的对象转为持久化对象
public void method2(){
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
Customer c=session.get(Customer.class, 1l);//持久化状态
c.setCust_name("李四");
//session.update(c);
tx.commit();
session.close();//c游离状态托管状态
}
hibernate进阶---一级缓存
缓存:提高效率,hibernate中的一级缓存也是为了提高操作数据库的效率
提高效率的手段1:提高查询效率

@Test
public void method3(){
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
Customer c1=session.get(Customer.class, 1L);
Customer c2=session.get(Customer.class, 1L);
Customer c3=session.get(Customer.class, 1L);
Customer c4=session.get(Customer.class, 1L);
System.out.println(c1==c2);//true
tx.commit();
session.close();//c游离状态托管状态
}
提高效率手段2:减少不必要的修改语句发送

@Test
public void method4(){
Session session=HibernateUtil.openSession();
Transaction tx=session.beginTransaction();
Customer c1=session.get(Customer.class, 1L);
c1.setCust_name("小明");
c1.setCust_name("李四");
tx.commit();
session.close();//c游离状态托管状态
}
hibernate中的事务
事务的特性:原子性、一致性、隔离性、持久性
事务的并发问题:1、脏读,2、不可重复读,3、幻/虚读
事务的隔离级别:读未提交--1、2、3
读已提交--2、3
可重复(mysql默认级别)--3
串行化--没有问题
如何在hibernate中指定数据库的隔离级别

在项目中如何管理事务
1、业务开始之前打开事务,业务执行之后提交事务,执行过程中出现异常就回滚事务
2、在dao层操作数据库需要用到session对象,在service层控制事务,也就是使用session对象完成。我们要确保dao层和service层使用的是同一个session对象。
3、在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了,我们开发人员只需要调用sf.getCurrentSession()方法即可获得与当前线程绑定的 session对象
注意1、调用getCurrentSession方法必须配合主配置中的一段配置

注意2、通过getCurrentSession方法获得的session对象,当事务提交时,session会自动关闭,不要手动调用close关闭
例如:
在service层

在dao层

hibernate中的批量查询
HQL查询--hibernate query language(多表查询,但不复杂时使用)
基本查询

条件查询


分页、查询

设置总记录数

原生SQL查询(复杂的业务查询)
基本查询 ---返回数组List

返回对象List

条件查询

分页查询

package com.test;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.domain.Customer;
import com.util.HibernateUtil;
public class Test02 {
@Test
public void method1() {
// 获得与当前线程绑定的session,是同一个session对象
Session s1 = HibernateUtil.getCurrentSession();
Session s2 = HibernateUtil.getCurrentSession();
System.out.println(s1 == s2);// true
}
@Test
public void method2() {
// 创建一个新的session对象
Session s1 = HibernateUtil.openSession();
Session s2 = HibernateUtil.openSession();
System.out.println(s1 == s2);// false
}
@Test
// hql基本查询
public void method3() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// 查询
// Customer c=session.get(Customer.class, 1l);
// String sql="select * from cst_customer";
// 书写HQL语句
String hql = "from Customer";
// 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
// 根据查询对象获得查询结果
List<Customer> list = query.list();
System.out.println(list);
// 关闭事务
tx.commit();
session.close();
}
@Test
// hql条件查询
public void method4() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// ?占位符
String hql = "from Customer where cust_name=?";
// 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
// 设置参数
// query.setLong(0, 1l);
// 增强版
query.setParameter(0, "aaa");
// 执行查询获得结果,唯一的一条结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
// 关闭事务
tx.commit();
session.close();
}
@Test
// hql条件查询
public void method5() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// 命名占位符
String hql = "from Customer where cust_name=:aa";
Query query = session.createQuery(hql);
query.setParameter("aa", "aaa");
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
tx.commit();
session.close();
}
@Test
// hql分页查询
public void method6() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
// 书写hql语句
String hql = "from Customer";
//创建查询对象
Query query = session.createQuery(hql);
// 设置分页信息limit 0,2
query.setFirstResult(0);
query.setMaxResults(2);
// 根据查询对象获取查询结果
List<Customer> list = query.list();
System.out.println(list);
tx.commit();
session.close();
}
}

浙公网安备 33010602011771号