Hibernate学习笔记02 主键生成策略、一级缓存、事务管理

持久化类概述

什么是持久化类

  • 持久化:将程序数据在持久状态和瞬时状态间转换的机制
  • 持久化类:一个java对象与数据库的表建立映射关系,则这个类在Hibernate中称为持久化类
  • 持久化类 = java类 + 映射文件

持久化类的编写规则

  • 对持久化类提供一个无参的构造方法 : Hibernate底层需要使用反射生成实例;
  • 属性需要私有化,对私有属性提供public的get和set方法:Hibernate可以获取对象属性或设置对象的属性值;
  • 对持久化类提供一个唯一标识OID与数据库主键对应:java中通过对象的地址区分是否为同一个对象,数据库中通过主键确。是否是同一条记录,Hibernate中通过持久化类的OID区分是否为同一个对象;
  • 持久化类中属性尽量使用包装类类型:基本数据类型默认是0,但0有很多歧义。包装类类型默认值为Null;
  • 持久化类不要使用final进行修饰:load延迟加载是通过继承来生成代理对象的。

主键生成策略

主键的分类

自然主键

解释:主键本身就是表中的一个字段(实体中的一个具体属性)

代理主键

解释:主键的本身不是表中必须的一个字段(不是实体的一个具体属性)

在实际开发中,尽量使用代理主键

自然主键参与到业务逻辑中,后期有可能需要修改源代码
遵循OCP原则,对程序的扩展是open的,对修改源码是close的

生成策略

  • increment:hibernate提供的自动增长机制,适用short/int/long类型的主键,在单线程程序中使用
  • indenity:适用于short/int/long类型的主键,使用的是数据库底层的自动增强机制(MySQL/MSSQL)
  • sequence:适用于short/int/long类型的主键,采用的是序列的方式(Oracle)
  • uuid:适用于字符串类型主键,使用Hibernate中的随机方式生成字符串主键
  • native:本地策略,可以在indenity和squence之间自动切换
  • assigned:hibernate放弃主键管理,需要通过手动编程或者用户自己设置
  • foreign:外部的,一对一的一种关联映射的情况先使用(了解)

持久化类的三种状态

Hibernate是持久层框架,通过持久化类完成ORM操作,Hibernate为了更好的管理持久化类,将持久化分成三种状态
瞬时态
这种对象没有唯一的标识OID,没有被session管理,则这种对象成为瞬时态对象
持久态
这种对象有唯一标识OID,被session管理,则这种对象成为持久态对象
管态
这种对象有唯一标识OID,没有被session管理,则这种对象成为托管态对象

如何区分这三种状态

/**
 * Hibernate持久类的三种状态
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        //Customer是一个持久化类,这是一个瞬时态对象,没有唯一标识ID,也没有被session管理
        Customer customer = new Customer();
        customer.setCust_name("张三");
        //得到唯一的标识OID,且被session管理,所以是持久态对象
        Serializable id = session.save(customer);
        session.get(Customer.class,id);

        transaction.commit();
        session.close();
        //有唯一的标识,但没有被session管理,所以是托管态对象
        System.out.println("客户名:" + customer.getCust_name());
    }
}

三种状态的转换(了解)

在这里插入图片描述
瞬时态
获取:
Customer customer = new Customer();
状态转换:

  • 瞬时——>持久
    sava(Object obj)、saveOrUpdate(Object obj);

  • 瞬时——>托管
    customer.setCust_id(1l);
    持久态
    获取:get()、load()、find()、iterate()

    Customer customer = session.get(Customer.class,1l);
    

    状态转换:

  • 持久——>瞬时
    delete();

    扫描二维码关注公众号,回复: 5834381 查看本文章
  • 持久——>托管
    close()、clear()、evict();
    托管态
    获取:

    Customer customer = new Customer();
    customer.setCust_id(1l);
    

    状态转换:

  • 托管——>持久
    update()、saveOrUpdate();

  • 托管——>瞬时
    customer.setCust_id(null);

持久态对象特性

自动更新数据库

/**
 * 持久态对象自动更新数据库
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        
        //获取持久态对象
        Customer customer = session.get(Customer.class,1l);
        customer.setCust_name("lisi")
        //不调用update
        //session.update(customer)
        transaction.commit();
        session.close();
    }
}
 持久态对象之所以能在不调用update的情况下,自动更新数据库是因为它的底层原理基于hibernate的一级缓存

一级缓存

什么是缓存

缓存是一种优化方式,将数据放入缓存中,使用时可以直接从缓存中直接获取,不用通过存储源

Hibernate的一级缓存

Hibernate框架中提供了缓存和抓取策略的优化手段,其中有两种缓存机制:一级缓存、二级缓存
Hibernate的一级缓存称为session级缓存,其生命周期与session一致,再带不可卸载。
Hibernate的二级缓存称为SessionFactory级缓存,需要配置的缓存,目前基本不用。

/**
 * HIbernate的一级缓存测试
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        /*
        //发送SQL语句
        Customer customer01 = session.get(Customer.class,1l);
        System.out.println(customer01);
        //不发送SQl语句
        Customer customer02 = session.get(Customer.class,1l);
        System.out.println(customer02)
        Systme.out.println(customer01 == customer02)
        */
        Customer customer = new Customer();
        customer.setCust_name("zhangsan");
        Serializable id = session.save(customer);
        
        Customer customer03 = session.get(Customer.class,id);
        System.out.println(customer03);
        
        transaction.commit();
        session.close();
    }
}

Hibernate一级缓存的结构

快照区

/**
 * HIbernate的一级缓存的快照区
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        
        Customer customer = session.get(Customer.class,1l);
        customer.setCust_name("wangwu");
        
        transaction.commit();
        session.close();
    }
}

一级缓存的清空

/**
 * HIbernate的一级缓存的清空
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();
        
        Customer customer1 = session.get(Customer.class,1l);//发送SQL语句查询,同时放入一级缓存
        //清空所有缓存
        //session.clear();
        //清空制定
        session.evite(customer1);
        
        Customer customer2 = session.get(Customer.class,1l);//发送SQL语句查询
        System.out.println(customer1);
        System.out.println(customer2);
        transaction.commit();
        session.close();
    }
}

Hibernate的事务管理

事务的回顾

什么是事务
事务指的是逻辑上的一组操作,组成这组操作的逻辑单元要么全部成功,要么全部失败。

事务的特性

  • 原子性:代表事务不可分割
  • 一致性:代表事务执行的前后,数据的完整性保持一致
  • 隔离性:代表一个事务在执行过程中,不应该受到其他事务的干扰
  • 持久性:代表事务执行完成后,数据持久到数据库中

安全性问题

  • 读的问题
    *脏读:一个事务读到另一个事务未提交的数据
    *不可重复读:一个事务读到另一个事务已经提交的update数据,导致在前一个事务多次查询结果不一致
    *虚读:一个事务读到另一个事务已经提交的insert数据,导致在前一个事务多次查询结果不一致
  • 写的问题
    *引发两类丢失更新

问题解决方案

  • 读问题
    1.设置事务的隔离级别
    Read uncommitted:以上读问题都会发生
    Read committed:解决脏读,但其余读问题有可能发生
    Repeatable read:解决脏读和不可重复读,但虚读有可能发生
    Seriallzable:解决所有读问题

设置事务隔离级别

<property name="hibernate.connection.isolation">4</property>

service层事务

Hibernate解决Service的事务管理

  • 改写工具类
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 15:16
 */
public class HibernateUtils {
    public static final Configuration cfg;
    public static final SessionFactory sf;
    static {
        cfg = new Configuration().configure();
        sf = cfg.buildSessionFactory();
    }

    public static Session openSession(){
        return sf.openSession();
    }

    public static Session getCurrentSession(){
        return sf.getCurrentSession();
    }
}
  • 配置完成
    <property name="hibernate.current_session_context_class" >thread</property>
    thread:Session对象的生命周期与本地线程绑定
    jta:Session对象的生命周期与JTA事务绑定
    managed:Hibernate委托程序来管理Session对象的生命周期

Hibernate其他的API

Query

Query接口用于接收HQL,查询多个对象

  • HQL(Hibernate Query Language): Hibernate查询语言,与SQL的语法极其相似,面向对象查询的语言。
import net.zjitc.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
/**
 * Hibernate Query的使用
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //简单查询
        //String hql = "from Customer";
        //条件查询
        //String hql = "from Customer where cust_name like ?";
        //分页查询
        String hql = "from Customer";
        Query query = session.createQuery("wangwu");
        //设置条件
        //query.setParameter(0,"wang%");
        //设置分页
        query.setFirstResult(3);
        query.setMaxResults(3);

        transaction.commit();
        session.close();
    }
}

Criteria

Criteria:QBC(Query By Criteria)
更加面向对象的一种查询方式

import net.zjitc.domain.Customer;
import net.zjitc.utils.HibernateUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import java.util.List;
/**
 * Hibernate Criteria的使用
 * @version 1.0
 * @autho ban
 * @date 2019/4/8 9:09
 */
public class HibernateDemo {
    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Transaction transaction = session.beginTransaction();

        //通过session获取Criteria对象
        Criteria criteria = session.createCriteria(Customer.class);

        /*条件查询
       criteria.add(Restrictions.like("cust_name","wang%"));
         */
        criteria.setFirstResult(3);
        criteria.setMaxResults(3);

        List<Customer> list = criteria.list();
        for (Customer customer : list){
            System.out.println(customer);
        }
        transaction.commit();
        session.close();
    }
}

SQLQuery

SQLQuery用于接收SQL。

猜你喜欢

转载自blog.csdn.net/weixin_43273271/article/details/89136951