hibernate之持久化类,主键生成策略,事务,缓存,查询api(02)

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/yjy91913/article/details/75269796

学习地图

持久化类
主键生成策略
持久化对象的三种状态(★持久态)
一级缓存(快照机制)
事务
查询的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 持久性:事务一旦结束(提交/回滚)数据就持久保持到了数据库.

若不考虑隔离性会产生的读问题
脏读
不可重复读
虚读

通过设置数据库的隔离级别就可以解决以上问题:

代表号码 状态 状态 二进制表示
1 read uncommitted 读未提交 0001
2 read committed 读已提交(oracle) 0010
4 repeatable read 可重复读(mysql) 0100
8 serializable 串行化 1000

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();
}
//获取和当前线程绑定的session
public 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

猜你喜欢

转载自blog.csdn.net/yjy91913/article/details/75269796