欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SSH框架之Hibernate第二篇

程序员文章站 2023-11-16 09:14:46
1.1 持久化类的编写规则 1.1.1 什么是持久化类? 持久化类 : 与表建立了映射关系的实体类,就可以称之为持久化类. 持久化类 = Java类 + 映射文件. 1.1.2 持久化类的编写规则 (1): 提供无参数的构造方法 (2): 类中的成员都是私有的private (3): 对私有属性提供... ......
1.1 持久化类的编写规则
        1.1.1 什么是持久化类?
            持久化类 : 与表建立了映射关系的实体类,就可以称之为持久化类.
            持久化类 = java类 + 映射文件.
        
        1.1.2 持久化类的编写规则
            (1): 提供无参数的构造方法
            (2): 类中的成员都是私有的private
            (3): 对私有属性提供get/set方法
            (4): 属性尽量使用包装类类型                                : 默认值不同的,包装类默认值null,基本数据类型默认0.
            (5): 持久化类不要使用final进行修饰                        : 使用final修饰,延迟加载失效,变为立即加载.
            (6): 类中需要提供标识属性(oid), 与表中主键建立映射关系  : hibernate根据标识属性来判断对象是否是同一个的.
            
            持久化类就是一个特殊的javabean
        
            hibernate 中实体类的标识属性 : object identifie  简称oid属性
                    就是配置文件中对应主键的那个实体类属性.
                    
                    作用: 让hibernate来区分对象是否是同一个.
                            如果多个对象的标识属性值相同,hibernate会认为是同一个对象,存储数据会报错.
                            
            oid属性都是交给hibernate来维护:
                好处 : 不会用重复相同的oid属性.
                    不用自己去写代码保证非空唯一.
            
    1.2 hibernate 主键生成策略:
        1.2.1 区分自然主键和代理主键
            自然主键 : 创建表的时候,使用的是实体中的自身属性作为表的主键.
                例如 : 创建一张人员表,可以用自生的身份证号(唯一的不可重复)作为主键.
                
            代理主键 : 创建表的时候,使用的不是实体中的自身的属性作为主键,创建一个不相关的字段作为主键.
                例如 : 创建一张人员表,不使用自生的身份证号(唯一的不可重复的)作为主键,用另外创建一个id作为主键.
                
            尽量使用代理主键.如果选用自然主键,当主键需要参与到业务逻辑中,有可能需要改变很多的设计和代码.
            
        1.2.2 的主键生成策略
            主键不应该由用户自己维护,应该统一管理,那么hibernate就提供了主键统一管理的方式: 主键生成策略.
            
            increment : 自动增长, 是hibernate中提供一种自动增长方式,不是数据库中的自动增长.(适用于short,int,long类型的主键)
                            首先使用 select max(cust_id) from cust_customer;将这个最大值 + 1 作为下一条记录的主键.
                            对于并发访问数据库不适用.
                            
            identity  : 自动增长, 适用于short,int,long类型的主键,使用的是数据库自动增长机制.不是所有数据库都支持自动增长,比如oracle没有自动增长.
            
            sequence  : 序列, 适用于short,int,long类型的主键,使用序列方式完成主键的生成.必须是支持序列的方式的数据库.oracle的自动增长.
                
            native       : 本地策略,根据底层的数据库不同,自动选择使用identity还是sequence.
            
            uuid       : 随机字符串,适用于字符串类型的主键.
            
            assigned  : hibernate不维护主键,开发人员需要手动设置主键.
            
            总结: 以后如果是针对是数值型,选择用native,如果是varchar类型,可以选择用uuid
                但是也可以不用hibernate维护,自己在程序中手动设定唯一非空(assigned)
                            
    1.3 持久化类的三种状态
        1.3.1 hibernate 的持久化类的三种状态.
            hibernate框架为了更好管理持久化类,将持久化类分成了三种状态.
                瞬时态 : 没有持久化标识oid,没有被session操作管理.
                持久态 : 有持久化标识oid,已经被session操作管理.
                脱管态(离线态) : 有持久化标识oid,没有被session操作管理.
            
        1.3.2 区分持久化类的三种状态
            public void demo1() {
                session session = hibernateutils.opensession();
                transaction transaction = session.begintransaction();
                
                //瞬时态 : 没有持久化标识oid,没有被session管理.
                customer customer = new customer();
                customer.setcust_name("黄天华");
                
                //持久态 : 有持久化标识oid,已经被session管理
                serializable id = session.save(customer); 
                system.out.println(id);
                
                transaction.commit();
                session.close();
                
                //脱管态 : 有持久化标识oid,没有被session管理.
                system.out.println(customer.getcust_name());
                
            }
            
        1.3.3 三种状态的转换(面试题)
            瞬时态 : 没有持久化标识oid,没有被session管理.
                获得:
                customer customer = new customer();
                状态转换:
                    瞬时 --> 持久 : save,saveorupdate
                    瞬时 --> 托管 : customer.setcust_id(1l);
                    
            持久态 : 有持久化标识oid,已经被session管理
                获得 : 只要是涉及到查询方法都是直接获得持久态对象.
                customer customer = session.get(customer.class,1l);
                状态转换
                持久 --> 托管 : close
                持久 --> 瞬时 : delete
            
            脱管态 : 有持久化标识oid,没有被session管理
                获得 
                customer customer = new customer();
                customer.setcust_id(1l);
                状态转换 : 
                托管 --> 持久 : save,update,saveorupdate
                托管 --> 瞬时 : customer.setcust_id(null)
                
            持久态 : 只要涉及到查询返回的就都是持久态类的持久态对象.
                特点 : 如果持久态对象修改完属性,不需要执行更新操作,会自动更新数据库数据.
            
        1.3.4 持久态可以自动更新数据库
            
            public void demo2() {
                session session = hibernateutils.opensession();
                transaction transaction = session.begintransaction();
                //获得持久态对象
                customer customer = session.get(customer.class,1l);
                customer.setcust_name("王宝强");
                //session.update(customer);//没有手动调用update方法,但是也可以更新数据库
                transaction.commit();
                session.close();
            }

    1.4 hibernate的一级缓存
        1.4.1 缓存的概述
            1.4.2 hibernate 的一级概述:
            hibernate框架本身的性能不是很好,但是hibernate提供了很多的性能优化的手动,比如,缓存.
            
            hibernate框架提供了两个级别的缓存:
                
            一级缓存: 称为session级别的缓存.因为一级缓存的生命周期与session一致的.自带的,不可卸载的.(由session中一系列的java集合构成的)
            
            二级缓存: 称为sessionfactory级别的缓存.需要进行配置的缓存的插件.默认不开启的.ehche == redis
            
            ps : 除了删除,增改查和数据库打完交道,都会往一级缓存中留一份.
                但是session只要关闭,一级缓存的数据全部清空.
                
            原因: 一级缓存的存在

            原理:
                session.get(customer.class, 1l)  // 去数据库查询,查完了之后放在一级缓存中
                                        一级缓存
                                            存储区
                                                放一份
                                            快照区
                                                备份一份

                ct.setcust_name("rose1234");   // 去一级缓冲中的存储区修改了内容,但是快照区不修改
                                        一级缓存
                                            存储区
                                                修改了
                                            快照区
                                                以前的


                tx.commit();      // 去一级缓存中,将存储区和快照区的数据都拿出来对比
                            一致: 什么都不做
                            不一致: 自动发送update语句做数据的数据更新
                
            1.4.3 证明一级缓存的存在:
                public void demo1() {
                    session session = hibernateutils.ipensession();
                    thransaction transaction = session.begintransaction();
                    
                    customer customer = new customer();
                    customer.setcust_name("好强");
                    
                    serializable id = session.save(customer);
                    session.get(customer.classmid);//没有发烧sql语句.
                    
                    customer customer1 = session.get(customer.class,1l);//发送sql语句去查询
                    system.out.println(customer1);
                    customer customer2 = session.get(customer.class,1l);//不发送sql语句
                    system.out.println(customer2);
                    
                    transaction.commit();
                    session.close();
                    
                }

        一级缓存区里面有缓存区和快照区,当把数据重新设置以后,更新缓存区,进行commit提交,会对比一级缓冲区里面的缓存区和快照区是否一致,
        如果一致,则不更新数据库;如果不一致,则重新存储到快照区,并更新数据库.
    
        1.4.5 一级缓存的管理的方法 : 清空一级缓存的数据
            clear,evict,close 管理一级缓存的相关的方法.
            clear 可以清空一级缓存的所有数据.
            evict 可以清空一级缓存的某一个对象的数据.
    
    1.5 session的绑定(threadlocal)
        1.5.1 hibernate中设置与当前线程绑定的session的使用
        <!-- 设置与当前线程绑定的session -->
        <property name="hibernate.current_session_context_class">thread</property>
        
    1.6    hibernate的其他的api
        在hibernate中,查询批量数据的方式:
                query方式 : 如果是使用这种方式做查询,又被称作为hql查询.
                criteria方式 : 如果是使用这种方式做查询,又被称作为qbc查询.
        
        1.6.1 query : hql查询
            接收一个hql进行查询 : hql-hibernate query language hibernate查询语言,与sql语言语法很相似的一个语言.面向对象.query接口,hql面向对象的查询.查询都是对象.
                @test
            /**
             * query接口
             * hql面向对象的查询.查询都是对象
             */
            public void demo1(){
                session session = hibernateutils.getcurrentsession();
                transaction transaction = session.begintransaction();
                
                // 查询全部客户信息:
                /*query query = session.createquery("from customer");
                list<customer> list = query.list();
                
                for (customer customer : list) {
                    system.out.println(customer);
                }*/
                
                // 条件查询
                /*query query = session.createquery("from customer where cust_name like ?");
                // 设置参数
                query.setparameter(0, "郝%");
                list<customer> list = query.list();
                for (customer customer : list) {
                    system.out.println(customer);
                }*/
                
                // 分页查询:
                query query = session.createquery("from customer");
                // 从哪开始的
                query.setfirstresult(3);
                // 每页显示记录数
                query.setmaxresults(3);
                
                list<customer> list = query.list();
                for (customer customer : list) {
                    system.out.println(customer);
                }
                transaction.commit();
            }
            
        1.6.2 criteria : qbc查询
            qbc-query by criteria 条件查询.更加面向对象化查询语言.
            @test
            /**
             * qbc查询:query by criteria
             */
            public void demo2(){
                session session = hibernateutils.getcurrentsession();
                transaction transaction = session.begintransaction();
                
                // 查询全部:
            /*    criteria criteria = session.createcriteria(customer.class);
                list<customer> list = criteria.list();
                for (customer customer : list) {
                    system.out.println(customer);
                }*/
                
                // 条件查询
                /**
                 * ==     eq
                 * >        gt                 
        * >=    ge        
                 * <        lt        
                 * <=    le        
                 * <>    ne        
                 * in   in
                 * like like
                 * 
                 */


                /*criteria criteria = session.createcriteria(customer.class);
                // criteria.add(restrictions.eq("cust_name", "郝天一"));
                criteria.add(restrictions.like("cust_name", "郝%"));
                list<customer> list = criteria.list();
                for (customer customer : list) {
                    system.out.println(customer);
                }*/
                
                // 分页查询
                criteria criteria = session.createcriteria(customer.class);
                criteria.setfirstresult(3);
                criteria.setmaxresults(3);
                list<customer> list = criteria.list();
                for (customer customer : list) {
                    system.out.println(customer);
                }
                
                transaction.commit();
            }