温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Hibernate入门三

发布时间:2020-04-05 09:19:57 来源:网络 阅读:597 作者:小咴 栏目:开发技术
    使用Hibernate最大的目的就是对数据库进行crud操作。在讲解之前,我们需要了解持久化以及持久化对象的三种状态。

 

什么是持久化

持久化就是把内存中的数据永久的存储到数据库中

 

什么是持久化类

持久化类就是Java类与数据库建立的一种映射关系,并把这个类称做持久化类。实际上,就是一张数据表中的字段与类中的属性字段相对象的类。

 

持久化类的编写规范

1.需要提供无参数的构造方法
  因为Hibernate通过反射机制生成类的实例
2.需要私有属性,并提供对应的get和set方法
  因为Hibernate底层会对获取到的数据惊醒封装
3.属性尽量使用包装类类型
   区分空和null
4.类中必须存在一个唯一标识 OID与表中的主键对应
   Hibernate利用这个这个唯一标识来区分内存中是否是同一个持久化类
5.不要使用final修饰类
  因为Hibernate有加载延迟机制,这个机制会产生代理对象。代理对象是通过字节 码增强技术来完成的,其实就是通过产生子类的方式,如果使用final修饰持久化类,这个机制就会失败。加载延迟机制是一种优化的手段。

 

Hibernate主键生成策略

主键的类型

  1. 自然主键
    把具有业务含义的字段作为主键,称为自然主键。比如,客户的姓名(必须保证姓名不重复,唯一,非空),这类主键往往会因为业务的改变重新设计表,造成数据库维护困难。
  2. 代理主键
    把具有非业务字段作为主键,称为代理主键。通常是ID,类型是整数类型(比字符串节省空间)
  3. Hibernate提供了几个内置主键生成策略
    1.increment:用于short int long类型。以自动增长的方式,每次增量是1。
    2.identity:采用底层数据库本身提供的主键生成标识,前提是数据库支持自动增长的类型。
    3.sequence:Hibernate根基底层序列生成标识符,前提是数据库支持序列。
    4.native:根据底层数据库生成能力来判断生成identity、sequence、hilo中的一种。适合跨数据库开发。
    5.uuid:采用128位uuid算法生成标识符
    6.assigned:由Java程序负责生成标识符。如果不指定id的generator属性,默认使用该属性。适合自然类型。

 

Hibernate持久化对象的三种状态

  1. 瞬时态
    也称为临时态,托管态,实例是new出来的。不存在唯一标识OID,也没有和Hibernate Session关联
  2. 托管态
    也称为离线态,游离态。当某个持久态状态的实例与session失去关联的时候就变成为托管态。但是,托管态对象仍然存在唯一 标识OID,与数据库中的数据存在关联,只不过托管态对象发生改变的时候,Hibernate无法检测到。
  3. 持久态
    对象存在OID,并且与Session关联。值得注意的是,持久态对象在是事务还没有提交之前变成持久态的。

下面通过列举例子来说明上述内容

@Test
    public void demo() {

        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        // 瞬时态,此时没有OID,也没有与session关联
        User user = new User(); 
        user.setUsername("robin");

        Serializable save = session.save(user); // 持久态

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

        // 托管态,此时session关闭,没有与session关联,但是有OID
        System.out.println(user);  
    }

Hibernate入门三

转换关系
 
瞬时态
1.瞬时态 -- 持久态
  调用save()或者saveOrUpdate()
2.瞬时态 -- 托管态
  为瞬时态添加 OID
 
持久态:可以从Session get() load()方法获取,或者Query对象等
1.持久态 -- 瞬时态
  session.delete()删除持久态化对象
2.持久态 -- 托管态
  session.evict()、clear()、close()方法。evict()用于清除一级缓存中的某一个对象,clear()用于清除一级缓存中的所有对象, close()关闭session,并且清除一级缓存。
 
托管态
1.托管套 -- 持久态
  执行update()、saveOrUpdate() lock()等
2,托管态 -- 瞬时态
  把对象的OID设置为null

 

持久态对象可以自动更新数据库

依赖Hibernateu一级缓存

@Test
    public void demo() {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSession();
            transaction = session.beginTransaction();

            User user = session.get(User.class, 2);
            user.setUsername("Robin");
           // session.update(user); 这句话可以省略,因为持久态的对象会自动更新数据库

            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        }
    }
}

 

Hibernate一级缓存

缓存是计算机为了提高读取速度而设计的。通常介于应用程序和永久性存储介质之间。提高应用的运行能力,通常是内存。
 
Hibernate缓存分为一级缓存和二级缓存(redis替代),一级缓存是Hibernate内置缓存,不能删除。
 
Hibernate一级缓存实际上就是session缓存。Session缓存是一个内存空间,存放相互管理的Java对象。在使用对象查找的时候,会使用OID在Hibernate一级缓存中进行查找,如果查找到了,就返回此对象,否则,就会去数据库查找与之相同OID的对象。
 
只要session实例没有结束生命周期,存放在它上面的缓存也不会消失。

    一级缓存的特点

    当应用程序调用Session的save()、update、saveOrUpdate()的时候,Session缓存中没有相应的对象的时候,Hibernate会自动的从数据库中提取对应的数据加载到一级缓存中

    当应用程序调用Session load()、get(),以及Query中的、list()、iterator()的时候,Hibernate首先会从以及缓存中寻找对象,如果存在则不需要去数据库中查找。,如果没有则从数据库中获取并加载到一级缓存中

    当调用Session.close()的时候,session缓存会被清空。

 

测试一级缓存

观察控制台输出的SQL语句

@Test
    public void demo() {
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        /**
         * 查询两次
         */
        /**
         * 第一次执行你会查询数据库
         * 第二次查询只会去缓存中寻找
         */
        User user = session.get(User.class, 1);
        User user1 = session.get(User.class, 1);

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

 

一级缓存内部结构

    Hibernate向一级缓存中存储数据的时候,会拷贝一份数据放在Hibernate快照区,当使用事务提交之后,会根据OID比较一级缓存中的数据和快照区中的数据是否一致,如果不一致,则执行更新操作,并且同步快照区的数据,否则则不执行任何操作。

 

Hibernate对事务的控制

 

  • 什么是事务?
    通常对数据库的操作过程中,一项事务会有一条或者多条SQL语句,只有当所有的语句正常执行的时候,所有的操作才会正常完成。如果中间出现异常现象,那么所有的语句执行都不成功。换句话说,对于一组操作,要么全部成功,要么全部失败。
     
  • 事务的四个基本特性
    原子性 一致性 隔离行 持久性
    原子性:对事务的操作,要不全部成功,要么全部失败。
    一致性:事务完成的时候,必须使所有的数据保持一致。
    隔离性:一个事务不能被另外一个事务干扰。
    持久性:一旦提交了事务,对数据库进行了操作,所有的操作就不可逆。永久性的被改变。
     
  • 事务并发引发的问题
    脏读 不可重复读 幻读(虚读)
    脏读:一个事务读取到另一个未提交事务的数据
    不可重复读:一个事务中读取到另外一个事务已提交的update数据,造成同一个事务中多次读读取数据不一致
    幻读:一个事务中读取到另外一个事务已提交的insert数据,造成同一个事务中多次读读取数据不一致
     
  • 事务的隔离级别
    读未提交(read uncommitted 1级):允许读取还未提交的数据,会造成脏读,不可重复读,幻读
    已提交读(read committed 2级):允许在事务并发时,读取已经提交的数据,可防止脏读
    可重复读(repeatable read 4级):对相同字段的多次读取结果是一样的,可以防止脏读,不可重复读
    幻读(serializable 8级):提供严格的事务隔离,可防止脏读,不可重复读,幻读

 

Hibernate事务管理

 

  • 设置事务隔离级别(在核心配置文件中配置)
    <property name="hibernate.connection.isolation">4</property>
  • 在业务层处理事务的方法
    1.在业务层中获取session,把它传递给持久层
    2.使用ThreadLocal将业务层获取到的session绑定到当前线程中去。然后到业务层获取的时候获取当前线程的session.

      <property name="hibernate.current_session_context_class">thread</property>
        sessionFactory.getCurrentSession()
        可以不需要关闭session,线程结束之后会自动关闭
    
        thread: Session对象的生命周期与本地线程绑定
        jta:Session对象的生命周期与JTA事务绑定
        managed:Hinernate委托程序来管理Session对象的生命周期

 

Hibernate其它的API

  

  • Query
  • Criteria
  • SQLQuery
     

    Query是面对对象的Hibernate查询操作。通过session.createQuery(),传递一个HQL语句,获取Query对象。

@Test
    public void demo() {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSession();
            transaction = session.beginTransaction();

            /**
             * 创建Query
             * 调用对象的方法
             */
            Query query = session.createQuery("from User");

            List<User> list = query.list();
            for (User user : list) {
                System.out.println(user);
            }

            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        }
    }

Criteria是一个完全面对对象,可扩展的条件查询API,它不需要考虑数据库底层的实现,以及SQL语句的编写。它是Hibernate核心查询对象,又称为OBC(Object By Criteria)

@Test
    public void demo() {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSession();
            transaction = session.beginTransaction();

            /**
             * Criteria
             *  创建Criteria对象
             *  调用方法
             */
            Criteria criteria = session.createCriteria(User.class);
            List<User> list = criteria.list();
            for (User user : list) {
                System.out.println(user);
            }
            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        }
    }

SQLQuery用来接收SQL语句,需要我们手动封装数据

@Test
    public void demo03() {
        Session session = null;
        Transaction transaction = null;
        try {
            session = HibernateUtil.getSession();
            transaction = session.beginTransaction();

            /**
             * 对象
             * 调用方法
             */
            String sql = "select * from `tb_user`";
            SQLQuery sqlQuery = session.createSQLQuery(sql);

            sqlQuery.addEntity(User.class);

            List<User> list = sqlQuery.list();

//            List<Object[]> list = sqlQuery.list();
//            for (Object[] user : list) {
//                System.out.println(Arrays.toString(user));
//            }

            for (User user : list) {
                System.out.println(user);
            }

            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        }
    }
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI