zoukankan      html  css  js  c++  java
  • Hibernate持久化

    一、主键生成策略

      1)主键分类:1.自然主键:主键本身就是表中的某一个字段,实体中的一个具体属性,对象本身唯一的特性。

              例如:创建一个学生,把其身份证号设为主键

             2.代理主键:本身不是表中的一个必须的字段,

              例如:创建一个学生,设置sid为主键。

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

      2)主键生成策略:在使用代理主键时,尽量自动生成主键,不让用户手动输入。

               在hibernate中,为了减少程序的编写,内部提供了多种主键生成策略

              1.increment:

                1.1自动增长策略:是适用于整型(long , short,int )

                1.2原理:首先发送一条语句,select max(id) from 表,然后加一。即查询最大id,然后进行加1。

                1.3在单线程中使用,不要在多线程中使用。

              2.identify

                2.1自动增长:是适用于整型(long , short,int )

                2.2原理:使用的是数据库底层的增长策略,适用于有自动增长的数据库,如mysql。

                2.3多线程安全。

              3.uuid 

                3.1适用于字符串类型的主键,使用hibernate中随机生成字符的主键。

              4.native

                4.1 自动增长,会根据所采用的数据库类型,自动变成identify(masql)或sequence(oracle)

              5.assigned

                 hibernate不会帮你管理主键,需要手动调用,或通过程序生成。

              一般开发中使用uuid与native。

    二、持久化

       1)什么是持久化:将内存中的一个对象存储到数据库中的过程。

       2)什么是持久化类:一个java类与数据库类建立的映射关系(java类+映射文件)

       3)持久化类编写规则:

          1.对持久化类提供一个无参的构造方法(一个类,如果没有构造方法,默认存在一个无参构造方法,如果重写了,则不会生成无参构造方法)。

            因为其内部通过反射创建对象,没有构造方法就无法创建对象。

          2.对内部私有的字段,必须提供get,set方法。(否则,hibernate无法获取对象的值)

          3.持久化类中提供一个oid与数据库中的主键对应。

          4.持久化类中的属性尽量使用包装类型(包装类型默认值是null,基本数据类型为数字)

          5.持久化类不能使用final来修饰。

    三、持久化类的划分

      1)hibernate为了更好的管理持久化类,将持久化类分为三种状态。

        1.瞬时态:没有唯一的oid,没有被session管理。

        2.持久态:有唯一oid,被session管理。

        3.游离态/托管态/离线态:有唯一oid,但是没有被session管理

      2)三种状态划分:

         1.瞬时态:刚被new出来,还没有设置id,没有被session管理。

         2.持久态:已经有id了,调用session方法,把对象给session才被session管理。

              当对象处于持久态时,可以自动更新数据库。

         3.游离态:把session关闭时,对象处于游离态。

       @Test
        public void test3(){
            /*直接创建对象修改:如果没有指定其他字段,会把其他字段设为null*/
            Session session = HibernateUtil.openSession();
            Transaction transaction = session.beginTransaction();
            //更新操作
            customer customer = new customer();//瞬时态
            customer.setCust_id(1L);
            customer.setCust_name("wzh");
            session.update(customer);//持久态
            customer.setCust_name("123");//处于持久态的对象具有更新数据库的能力
            transaction.commit();
            session.close();//游离态
            HibernateUtil.sessionFactory.close();
        }

          三种状态相互转换:

    四、一级缓存

      1)什么是缓存:是一种优化方式,将数据存入内存中,使用的时候,直接从缓存中获取,不用直接到存储源(数据库)中获取。

          一级缓存:hibernate自带

          二级缓存:现在一般使用radis,不使用其自带的。

      2) 一级缓存:1.session级别的缓存,

             2.声明周期与session一致,一级缓存由session中的一系列集合构成。

             3.是自带的,不可卸载。(二级缓存是sessionFactory级别的)

      3)一级缓存的特点:查询更新是先检查缓存中有没有相应数据,有则不会查询数据库,没有就查询数据库,并把查询到的记录同步到缓存。当调用session.close方法时,缓存清空。

      4)一级缓存内部结构:

         快照区:使用id进行查询数据库时,将查询的结果放到session的一级一级缓存中,同时复制一份数据,放置到session的快照中。

             当使用tr.commit()时,同时清理session的一级缓存(flush)

             当清理session一级缓存时,会使用Oid判断一级缓存中的对象与快照中的对象进行比较,如果两个对象中,对象属性发生变化,则执行update语句,此时

             更新数据库,更新成一级缓存中的数据,如果两个对象中属性一致,此时不执行update操作。

              (存入数据时,存入数据库的同时存入缓存区与快照区,更新时,只是更新缓存区,提交事务时,对比快照区与缓存区对象是否一样,不一样,说明已经进行了更新操作

               这时候才发送一条更新的sql给数据库,进行更新)

              目的:确保数据库中的数据一致。

    五、事务管理

      1)事务:逻辑上的一组操作,要么都完成,要么都失败。

      2)事务特性:原子性,隔离性,一致性,持久性。

      3)事务的隔离级别

      4)在hibernate中设置事务的隔离级别:在核心配置文件中hibernate.cfg.xml中,设置

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

          通过数字设置隔离级别。

      5)事务的开启一般在service层开启。开启的过程需要保证与外部dao中用的时同一个连接对象(session),开发中,通常将session绑定到ThreadLocal中。 

        事务业务层连接:

          1.为什么要在业务层使用事务:业务层可以调用多个dao层的操作

          2.在业务层使用事务时,必须保证获取事务的连接和dao层操作的连接是同一个,否则,就管理不了对应的操作。

          3.使用jdbc中事务业务层的处理方法:

              3.1 向下传递:开始在业务层先创建好一个连接,传给dao层,让dao层使用这个连接执行操作。

              3.2 使用ThreadLocal对象:在service方法当中把创建的连接绑定到对应的ThreadLocal当中,在dao方法中,通过当前线程获取连接对象。

          4.hibernate中的处理方法:

              4.1Hibernate框架内部已经绑定好了ThreadLocal,在SessionFactory中,提供了一个方法,getCurrentSession()方法,获取当前线程中的session。

                但是此方法默认不可使用。

              4.2需要在核心配置文件中配置

              <property name="current_session_context_class">thread</property>
              创建一个session绑定到当前线程。
               4.3通过它来操作时,不需要close,执行结束会自动close
        在utils中:
        public static Session getCurrentSession(){
            //从ThreadLocal中获取的session
            Session session =sessionFactory.getCurrentSession();
            return  session;
        }

        test中:

      @Test
        public void test3(){
            /*直接创建对象修改:如果没有指定其他字段,会把其他字段设为null*/
            Session session = HibernateUtil.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            //更新操作
            customer customer = new customer();//瞬时态
            customer.setCust_id(3L);
            customer.setCust_name("xxl");
            session.update(customer);//持久态
            //customer.setCust_name("123");//处于持久态的对象具有更新数据库的能力
            transaction.commit();
            //session.close();//游离态
            //HibernateUtil.sessionFactory.close();
        }
    
    
  • 相关阅读:
    Leetcode 204. Count Primes
    Leetcode 263. Ugly Number
    Leetcode 202. Happy Number
    Leetcode 258. Add Digits
    Leetcode 23. Merge k Sorted Lists
    BAT 批处理脚本教程
    入门训练 序列求和
    JAVA学习:方法
    大小之差
    java中length,length(),size()区别
  • 原文地址:https://www.cnblogs.com/UalBlog/p/10601770.html
Copyright © 2011-2022 走看看