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(); } }