hibernate之持久化类,主键生成策略,事务,缓存,查询api(02)
来源:互联网 发布:活动致辞知乎 编辑:程序博客网 时间:2024/06/06 18:40
学习地图
持久化类
主键生成策略
持久化对象的三种状态(★持久态)
一级缓存(快照机制)
事务
查询的api★★★
持久化类:
概述:javabean + 映射文件
编写规范:
必须是一个公共的具体的类(public class)
必须有一个无参构造器
字段私有,必须提供公共的访问字段的方法(get和set)
必须有一个oid属性和主键对应
字段尽量使用包装类修饰
类尽量不要使用final修饰(若使用final修饰,load方法和get一样了)
因为load的加强方法是 javassist或者cglib 动态代理
使用的继承方法
主键生成策略
主键类型分类
自然主键:使用实体中一个有具体业务意义的字段作为主键
例如:身份证号
★代理主键:使用实体中一个毫无任何具体业务意义的字段作为主键
例如 user_id product_id
hibernate中主键生成策略:
常见值:
(了解)increment:使用hibernate的自增策略(我们不用),类型整数,插入记录的时候,先去数据库中查询一下id的最大值,然后将最大值+1作为这条记录的id,我们一般不会用,因为多线程会出问题
★identity:hiberante使用数据库的自增策略,类型整数 代表:mysql
★sequence:hiberante使用数据库的序列策略,类型整数 代表:oracle
★★native:hiberante使用数据库的本地策略,类型整数 判断数据库的支持什么策略 我们可以简单的认为不是identity就是sequence
(理解)uuid:hibernate使用随机字符串
(了解)assigned:放弃hibernate维护主键.自己手动指定
我们一般选用uuid或者native
持久化对象的三种状态(★持久态)
(了解)瞬时态:对象没有oid,且没有和session关联
(★★)持久态:对象有oid,且和session关联
特点:持久态对象可以自动更新数据库(依赖于一级缓存)
(了解)脱管态:对象有oid,但没有和session关联
持久态验证
持久化三种对象
public void t1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //先创建一个对象 Customer c = new Customer("二毛"); c.setCust_source("网络营销");//瞬时态对象 // 保存 Serializable id = session.save(c);//持久态对象 tx.commit(); session.close(); System.out.println(c.getCust_id()+"::"+c.getCust_name());//脱管态对象 }
持久态对象可以自动更新数据库
public void t2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer c = session.get(Customer.class, 1L); c.setCust_name("二毛二"); //之前就该调用update 因为c是持久态对象,可以自动更新数据库,现在不需要调用update tx.commit(); session.close(); }
一级缓存(快照机制)
缓存:
介于硬件和程序之间的一种介质.提供程序的执行效率.减轻数据库的负载(访问次数)
查询数据的时候先从缓存中,若缓存没有再去mysql中查询,查询完成之后,还需要将记录放入缓存中一份.
hibernate封装了jdbc的操作.效率肯定没有jdbc高.hibernate为了提高他的执行效率,从而提供了一些优化手段(缓存和延迟加载)
在缓存中提供了一级缓存和二级缓存
一级缓存:
hibernate自带的,不能卸载,必须使用的.生命周期和Session的生命周期一样.所以有人把他也称之为Session级别的缓存
(了解)二级缓存:
不是hibernate自带的(ehcache),要想使用必须先导入jar包,然后配置才能使用.一般使用redis替代.
生命周期和SessionFactory的生命周期一样.所以有人把他也称之为SessionFactory级别的缓存
一级缓存:
就是一些java集合组成的.
分成了缓存区和快照区两部分.
放入数据的时候,放缓存区放入一份,往快照区放入一份.我们操作的时候,只操作缓存区.
当事务提交的时候,判断缓存区和快照区的数据有无改变
若改变:马上发送sql语句,更新数据库
若不改变:啥也不做
这个就是session级别的缓存
验证一级缓存是否存在:
1.查询一个对象两次
2.先保存一个对象,然后再查询
请看下面代码
@Test //查询一个对象两次 public void t(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer c1 = session.get(Customer.class, 1L); Customer c2 = session.get(Customer.class, 1L); System.out.println(c1 == c2);//输入为true tx.commit(); session.close(); }
@Test //先保存 再查询 public void t2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); //先保存 Customer c1 = new Customer("大毛"); session.save(c1); //在查询,查询的时候就先查缓存,如果缓存没有再去数据库拿 Customer c2 = session.get(Customer.class, 1L); System.out.println(c1 == c2); tx.commit(); session.close(); }
事务
javase中的事务
事务概念
事务特性: ACID
A:automicity 原子性:强调事务的不可分割.多条语句要么都成功,要么都失败。
C:consistency 一致性:强调的是事务的执行的前后,数据要保持一致.(例如 A转账B,两个人的钱数应该各有加减)
I:isolation 隔离性:一个事务不能收到其他事务的影响,
D:durability 持久性:事务一旦结束(提交/回滚)数据就持久保持到了数据库.
若不考虑隔离性会产生的读问题
脏读
不可重复读
虚读
通过设置数据库的隔离级别就可以解决以上问题:
hibernate如何设置隔离级别?
在核心配置文件中配置
<property name="hibernate.connenction.isolation">4</..>
事务加在哪一层?service
如何保证service层和dao层使用的同一个事务啊?
只需要保证service层和dao层使用同一个连接即可
若何保证service层和dao层使用同一个连接呢?
方式1:传递参数
方式2:使用线程绑定的方式(ThreadLocal)
hibernate如何使用事务,底层封装好了ThreadLocal
步骤:
1.在核心配置文件中配置 将session绑定到当前线程中
<!-- 开启与线程绑定的session --><property name="hibernate.current_session_context_class">thread</property>
2.factory.getCurrentSession();获取和当前线程绑定的session
注意:
此时的session不需要手动关闭
/*** 获取和当前线程绑定的session对象 * @return */public static Session getCurrentSession(){ return factory.getCurrentSession();}
//获取和当前线程绑定的sessionpublic class Demo4Thread { @Test public void t(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); tx.commit(); //session.close();//不需要手动关闭 }
查询的api★★★
5中检索方式
oid检索
get和load
对象导航检索(明天说)
sql检索(发送sql语句)
hql检索
qbc检索
hql检索★★
面向对象的查询语言.
获取查询对象Query
session.createQuery(String hql语句);
hql语句和sql类似,简单的写法 可以将sql中的表名和字段名用类名和属性名替代
查询所有
list()
uniqueResult() 唯一值
public class HQLDemo { @Test //查询所有 public void t1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //1.获取query对象 Query qq = session.createQuery("from Customer");//正确 //Query qq = session.createQuery("select c from Customer c");//正确 //Query qq = session.createQuery("select * from Customer");//错误 //2.查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
排序查询
hql : from Customer order by cust_id desc
@Test //排序查询 public void t2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("from Customer order by cust_id desc");//正确 //查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
分页查询
setFirstResult(int 开始索引)
setMaxResults(int 每页显示的条数)
@Test //分页查询 public void t4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("from Customer"); //设置分页参数 limit m,n; limit 0,3 等价于 limit 3; qq.setFirstResult(3); qq.setMaxResults(3); //查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
统计查询
hql : select count(*) from Customer
@Test //统计查询 public void t3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("select count(*) from Customer");//正确 //查询 /*List<Long> list = qq.list(); System.out.println(list);*/ Long obj = (Long) qq.uniqueResult(); System.out.println(obj); tx.commit(); }
条件查询
★方式1:按照位置设置参数 ? 占位符
hql:from Customer where cust_name like ? and cust_source = ?
setParameter(int 问号的索引,Object 参数值)
@Test //条件查询:1 按照位置设置参数 ? public void t5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("from Customer where cust_name like ? and cust_source = ?"); //设置参数 qq.setParameter(0, "%大毛%"); qq.setParameter(1, "网络营销"); //查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
(扩展)方式2:按照名称设置参数 :名称 占位符
hql:from Customer where cust_name like :name and cust_source = :ss
setParameter(String 参数的名称,Object 参数值)
例如:
setParameter(“name”,”%大毛%”)
@Test //条件查询:2 按照名称设置参数 :参数名称 public void t6(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("from Customer where cust_name like :name and cust_source = :ss"); //设置参数 qq.setParameter("name", "%大毛%"); qq.setParameter("ss", "网络营销"); //查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
投影查询(查询部分属性)
//投影查询 部分属性 默认将每条记录封装成object数组
//投影查询 部分属性封装成对象
/**
* 1.在持久化类提供相应的构造器
* 2.hql: select new 类名(属性1,属性2) from 类名;
*/
@Test //投影查询 部分属性 public void t7(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("select cust_name, cust_id from Customer"); //查询 List<Object[]> list = qq.list();//ArrayListHandler for (Object[] obj : list) { System.out.println(Arrays.toString(obj)); } tx.commit(); }
@Test //投影查询 部分属性封装成对象 /** * 1.在持久化类提供相应的构造器 * 2.hql: select new 类名(属性1,属性2) from 类名; */ public void t8(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取query对象 Query qq = session.createQuery("select new Customer(cust_name, cust_id) from Customer"); //查询 List<Customer> list = qq.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
qbc检索
query by criteria
更加面向对象的查询语言.全是api
获取Criteria对象
session.createCriteria(Class 持久化类的字节码对象)
查询所有
list()
uniqueResult()
@Test //查询所有 public void t1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取criteria对象 Criteria cc = session.createCriteria(Customer.class); //查询 List<Customer> list = cc.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
排序查询
addOrder(Order.asc|desc(属性名称))
@Test //排序查询 public void t2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取criteria对象 Criteria cc = session.createCriteria(Customer.class); //条件排序条件 cc.addOrder(Order.desc("cust_id")); //查询 List<Customer> list = cc.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
分页查询
setFirstResult
setMaxResults
@Test //分页查询 public void t3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取criteria对象 Criteria cc = session.createCriteria(Customer.class); //设置分页参数 cc.setFirstResult(0); cc.setMaxResults(3); //条件排序条件 cc.addOrder(Order.desc("cust_id")); //查询 List<Customer> list = cc.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
统计查询
setProjection(Projections.count|avg|sum|min|max(属性名));
setProjection(Projections.rowCount());
@Test //统计查询 public void t4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取criteria对象 Criteria cc = session.createCriteria(Customer.class); //cc.setProjection(Projections.count("cust_id"));//select count(cust_id) .. cc.setProjection(Projections.rowCount());//select count(*) .. Object obj = cc.uniqueResult(); System.out.println(obj); tx.commit(); }
条件查询
add(Restrictions.like|eq|gt|lt(String 属性名,Object 值));
@Test //条件查询 public void t5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取criteria对象 Criteria cc = session.createCriteria(Customer.class); //设置条件 cc.add(Restrictions.like("cust_name", "%大毛%")); cc.add(Restrictions.eq("cust_source", "网络营销")); //查询 List<Customer> list = cc.list(); for (Customer c : list) { System.out.println(c); } tx.commit(); }
离线查询:(多条件查询)
脱离session使用的对象. DetachedCriteria
在web层脱离session使用,封装条件,api几乎和Criteria一样
创建一个离线对象
DetachedCriteria dc = DetachedCriteria.forClass(Class 持久化类的字节码对象);
在dao层获取可以执行的对象 操作
Criteria cc = dc.getExecutableCriteria(session)
下面程序模拟三层
@Test public void t(){ //web层 String cust_name = null; String cust_source = null; /** * 之前的写法:接受条件 * cust_name = request.getParameter("cust_name"); * cust_source = request.getParameter("cust_source"); */ cust_name = "大毛"; //添加条件 DetachedCriteria dc = DetachedCriteria.forClass(Customer.class); //判断条件是否为空 if(cust_name!=null && cust_name.trim().length()>0){ dc.add(Restrictions.like("cust_name", "%"+cust_name+"%")); } if(cust_source!=null && cust_source.trim().length()>0){ dc.add(Restrictions.eq("cust_source", cust_source)); } //service层 //dao层 Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //获取一个可执行的对象 Criteria cc = dc.getExecutableCriteria(session); List list = cc.list(); tx.commit(); }
扩展:sql检索:
获取SqlQuery对象
session.createSqlQuery(String sql语句);
条件和分页还可以使用
setFirstResult
setParameter
查询所有
list方法返回值 List
- hibernate之持久化类,主键生成策略,事务,缓存,查询api(02)
- Hibernate持久化类、主键生成策略、持久户对象、一级缓存、事务和五种检索方式
- Hibernate持久化类与主键生成策略
- Hibernate持久化类与主键生成策略
- Hibernate学习-10:持久化类、主键生成策略
- hibernate_持久化类、主键生成策略
- Hibernate之主键生成策略
- Hibernate之主键生成策略
- Hibernate之主键生成策略
- Hibernate-主键映射之主键生成策略
- 【SSH】Hibernate学习(二)主键生成策略、对象状态、一级缓存、事务、HQL
- Hibernate主键生成策略之Hilo
- hibernate annotation之主键生成策略
- Hibernate之ID主键生成策略
- hibernate annotation 之 主键生成策略
- hibernate annotation 之 主键生成策略
- Hibernate进阶之ID主键生成策略
- hibernate annotation 之 主键生成策略
- 事先规划RTL结构
- TCP协议用在python和wifi模块之间
- 可能与不可能的边界:P/NP问题趣史
- Python爬虫从入门到懵逼-1
- 如何让子元素居于父元素底部
- hibernate之持久化类,主键生成策略,事务,缓存,查询api(02)
- 2012 浙大机试 Sharing
- 1026. 程序运行时间
- Git使用详细教程
- PyCharm 查看各种常用类型的方法
- The first one.
- [渗透&攻防] 二.SQL MAP工具从零解读数据库及基础用法
- 记一次解决Django 403
- 逆置/反转单链表+查找单链表的倒数第k个节点,要求只能遍历一次链表