Hibernate入门到精通

嫌弃排版乱的点击这里下载word版本



目录

Hibernate    2

Hibernate简介    2

Hibernate环境搭建    2

1.映射配置文件:    2

2.核心配置文件    3

Api内置对象    4

1. Configuration:配置对象    4

2. SessionFactory:(session工厂)    4

3. Session    4

Hibernate的五种检索方式    5

1.对象图导航检索    5

2. OID检索方式    5

3. HQL检索方式    5

4. QBC检索方式    5

5. SQL检索方式    6

Hibernate的多表关系    6

1.简介    6

2.一对多1里放集合)(&里放对象)    6

3.多对多(彼此往里放集合)    7

4.级联:(牵一发而动全身)    8

5.冗余sql(多余sql    8

Hibernate中的多表查询    8

Hibernate的优化    8

持久化类    9

1.简介    9

2.持久化对象的三种状态    9

一级缓存    9

 

 

hibernate工作在dao层负责和数据库的交互,应用它之前需要先创建表对象,用来封装数据,之后要敬请映射xml的配置,在映射配置里应用class标签配置类和表的映射,name属性配置类的全限定名,table属性配置表的名称,catalog属性是配置数据库,因为在核心文件里已经配置这里可以不配置,应用id标签配置主键name属性配置属性的名称 column配置表中主键属性的名称,id标签中generator标签用来配置主键生成策略,我们常用的class属性值是native(本地的)和uuid(字符串),property标签用来配置普通的属性和字段的映射,name属性名,column字段名,其中还有not-null="true"非空和unique="true"唯一,映射关系配置完后,配置hibernate的核心配置文件,其中配置hibernate的基本环境参数,其中要配置数据库的四个基本参数,数据库方言,显式sql和格式化sql,自动建表,整合c3p0,设置事物隔离级别,开启事物,基本环境搭建成功,下面就是使用,在dao层类中调用api使用,configuration用来初始化hibernate和加载配置文件,获取sessionFactory,它用来管理session,获取session,内置了一个数据源,是一个重量级对象,所以就像连接池一样建立一个工具类,用的时候,调用它就行。session是执行者,他可以进行增删改查的操作,还可以开启事物。为了线程安全,我们需要把当前的session绑定到当前的线程中,所以要在hibernate核心配置文件中,配置隔离级别,开启事物,并在工具类中用sessionFactory返回一个绑定线程的session,之后我们就可以进行操作了,增删改save,delete,update,查有五种方式,看下边,多表的话要在映射文件中配置多表关系,在1的映射文件上配置set标签,在&的映射文件上配置many-to-one标签。。。

 

Hibernate

Hibernate简介

hibernate是一个工作在dao层的框架,他良好的对JDBC进行了封装,使用了面对对象的思想操作数据库,可以自动生成sql语句,并执行。

Hibernate环境搭建

  1. 映射配置文件:

  • 1.1 简介

         作用:解释表和对象类之间关系

    基本说明:

名称(理论上可以随便写):     建议类名.hbm.xml

路径(理论上可以随便):        建议放在domain下

约束中的路径:原本需要在网上下载,在这里可以自己配置本地的

  • 1.2 映射配置介绍

    <?xmlversion="1.0"encoding="UTF-8"?>

    <!DOCTYPE hibernate-mappingPUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping>

        <classname="hibernate_day1.domain.Customer"table="cst_customer">

            <idname="cust_id"column="cust_id">

                <generatorclass="native"/>

            </id>

            <propertyname="cust_name"column=""/>

            <propertyname="cust_source"/>

        </class>

    </hibernate-mapping>

    class标签:(建立类和表的映射

name属性:

类的全限定名(项目里的相对位置)

table属性:

表名(若表名和类名一样的话,可以省略不写)(如果没有表的话可以在核心配置文件中写一个自动创建的属性,自动创建表)

catalog:

数据库的名称 (在核心配置文件中已经配置了,这里可以省略,如果两个都写了,以这个为主 )

id标签:class标签中,主键和属性的映射

name属性:

对象里属性的名称

column属性:

数据库里的字段名称    (主键名)

lenth属性:

字段的长度,如使用hibetnate生成表的时候lenth就要起做用了 (不写会有默认值)

type属性:

字段的类型,如使用hibetnate生成表的时候type就要起做用了 ;支持java类型,数据库类型,hibernate类型(默认),不写的话会根据class标签绑定的类的字段类型生成hibernate类型

generator标签:id标签中,主键生成策略

主键的分类:

☆代理主键:使用对象的一个毫无业务意义的属性作为主键。(以后用这个)

自然主键:使用对象的一个有业务意义的属性作为主键。(不常用)(如身份证)

class属性:

策略值

1.increment:使用的hibernate的自增策略,类型必须为整数,只适合在单线程用,因为他执行时是先查询id的最大值,将该条最大值加一设置为新的id 如果两条同时插入,会重复,线程不安全

2.identity:hibernate使用的是数据库的自增策略,类型必须为整数。代表:mysql

3.sequence:hibernate使用的是数据库的序列策略,类型必须是整数。代表:oracle

4.☆☆native:hibernate会检查我们使用的数据库支持什么策略就使用什么策略,对于我们来说不是identity就是sequence。(native单词的意思是 本地)

5.☆uuid:hibernate使用随机的字符串作为id

6.assigned:放弃hibernate的主键维护,自己手动的set进id

property标签:class标签中,普通字段和属性的映射

name属性:

对象里普通属性名称

column属性:

数据库里的普通字段名称    

lenth属性:

字段的长度,如使用hibetnate生成表的时候lenth就要起做用了 (不写会有默认值)

type属性:

字段的类型,如使用hibetnate生成表的时候type就要起做用了 ;支持java类型,数据库类型,hibernate类型(默认),不写的话会根据class标签绑定的类的字段类型生成hibernate类型

not-null属性:

true false 是否非空

unique属性:

是否唯一

 

  1. 核心配置文件

     

  • 1.1 简介

         作用:配置hibernate的环境的参数,基本信息,属性配置,加载映射文件(用mapping标签里的resource属性加载)

 

基本说明:

1.名称固定,位置建议放在src下

2.格式1;hibernate.properties(不能加载映射文件)

3.格式2:hibernate.cfg.xml (主要使用这个)

  • 1.2 映射配置介绍
    • 1.    导入约束文件

      位置在:Web App Libraries下的hibernate-core- /org.hibernate/hibernate-configuration-3.0.dtd

  1. 进行数据库的4个基本属性配置( 驱动,数据库地址,用户名,密码

    位置在:在解压出来的 hibernate-release-5.0.7.Final\project\etc\hibernate.properties里面找

  2. 设置hibernate的属性配置( 数据库方言,显式sql,格式化sql,有hibernate自动生成语句,整合c3p0,设置事物

    位置在:在解压出来的 hibernate-release-5.0.7.Final\project\etc\hibernate.properties里面找

  3. 加载映射文件

    <?xmlversion="1.0"encoding="UTF-8"?>

    <!--导入约束条件

        位置在:Web App Libraries下的hibernate-core- /org.hibernate/hibernate-configuration-3.0.dtd

    -->

    <!DOCTYPE hibernate-configurationPUBLIC

        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <session-factory>

            <!-- 要进行三个配置

                配置内容:

                    4个基本参数

                    hibernate的属性配置

                    映射文件加载

             -->

            <!-- 第一个:四个基本参数 驱动,数据库地址,用户名,密码-->

            <!-- 在解压出来的 hibernate-release-5.0.7.Final\project\etc\hibernate.properties里面找 -->

            <propertyname="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

            <propertyname="hibernate.connection.url">jdbc:mysql:///hibernate_day1</property>

            <propertyname="hibernate.connection.username">root</property>

            <propertyname="hibernate.connection.password">liqichen</property>

            <!-- 第二个:hibernate的属性配置-->

                <!-- 必须得有的属性 数据库方言-->

            <propertyname="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

                <!--是否显示sql语句 -->    

            <propertyname="hibernate.show_sql">true</property>

                <!-- 是否格式化sql语句 -->    

            <propertyname="hibernate.format_sql">true</property>

                <!-- 是否由hibernate生成建表语句(ddl语句),及如何生成

                    常见值:

                        create            由hibernate生成建表语句,若之前表存在,先删除表,在创建表 (一般测试用)

                        create-drop    由hibernate生成建表语句,若之前表存在,先删除表,在创建表,若彻底使用完后删

    除表 (测试使用)

                        update            若之前表存在,直接更新使用;若之前没有该表,先创建在使用

                        validate        使用的时候先校验映射文件和表是否对应,若对应直接使用,若对应不上就会抛异常

                 -->

            <propertyname="hibernate.hbm2ddl.auto">update</property>

<!-- 配置C3P0连接池 -->

            <propertyname="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>

            <!--在连接池中可用的数据库连接的最少数目 -->

            <propertyname="c3p0.min_size">5</property>

            <!--在连接池中所有数据库连接的最大数目 -->

            <propertyname="c3p0.max_size">20</property>

            <!--设定数据库连接的过期时间,以秒为单位,

            如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->

            <propertyname="c3p0.timeout">120</property>

            <!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->

<propertyname="c3p0.idle_test_period">3000</property>

 

<!-- 设置事务的隔离级别 -->

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

        <!-- 开启与线程绑定的session -->

<propertyname="hibernate.current_session_context_class">thread</property>

 

        <!-- 第三个:映射文件的加载 -->

            <mappingresource="hibernate_day1/domain/Customer.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

Api内置对象

  1. Configuration:配置对象

    作用:

    1.加载核心配置文件

    new Configuration()    默认加载的是src目录下的hibernate.Properties

    new Configuration().configure();    默认加载的是src目录下的hibernate.cfg.xml

    new Configuration().configure(path); 如果不在src下使用

    2.创建sessionFactory

    configuration.buildSessionFactory();

    3加载映射文件

    若配置文件为properties或者在xml文件中没有加载映射文件,可以通过addResource方法加载映射文件

     

  2. SessionFactory:(session工厂)

    作用:

    1.初始化hibernate

    2.获取session

    sessionFactory.openSession();

    3.底层维护了一个数据源(就是一个链接池)

    注意:这是一个重量级的对象:创建和销毁时特别消耗时间,一般一个项目只有一个SessionFactory对象

    4抽取一个工具类:(sessionfactoy 只需要创建一次获取session)

    4.1普通工具类 (utils)

    public class HibernateUtils {

        private static final Configuration config;

        private static final SessionFactory factory;

        static{

            config=new Configuration().configure();

            factory = config.buildSessionFactory();

        }

        public static Session openSession(){

            return factory.openSession();

        }

    }

    4.2事物工具类 (utils)

    在核心配置文件配置后

    publicclass HibernateUtils {

        privatestaticfinal Configuration config;

        privatestaticfinal SessionFactory factory;

        static{

            config=new Configuration().configure();

            factory =config.buildSessionFactory();

        }

        publicstatic Session getCurrentSession(){

            returnfactory.getCurrentSession();

        }

    }

  3. Session

    作用:

    1.开启事物

    session.beginTransaction();

    1. 和数据库交互

      增删改查

    Hibernate的五种检索方式

    1. 对象图导航检索

    对象图导航检索就是,在一对多的情况下,每一个&对象都对应一个1,可以通过session获取指定的&对象,再通过&对象获取包含的那个唯一的1

    例:LinkMan linkMan = (LinkMan)session.get(LinkMan.class,1L);
            Customer customer = linkMan.getCustomer();

  4. OID 检索方式

    就是知道了对象的id,直接用session的get(),load()方法来找到对象

    例:Customer customer = (Customer )session.get(Customer.class,1);
            Customer customer = (Customer )session.load(Customer.class,1);

  5. HQL 检索方式

    HQL是面向对象的查询语言,和sql有些相似,但是HQL中的概念是操作类,对象,对象和属性,Hibernate提供了Query接口,是专门的HQL查询接口,完整的HQL语句结构如下

    selectfromwheregroup byhavingorder byasc/desc

    在检索所有的记录时,可以省略select,要注意的是这里检索的是类名,类名是要区分大小写的,关键字不区分

    检索方式:

    基本查询:

    Query query = session.createQuery("from Customer");
    List<Customer> list = query.list();

    别名查询:

    Query query = session.createQuery("from Customer c");
    Query query = session.createQuery("select c from Customer c");

    排序查询:

    Query query = session.createQuery("from Customer order by cust_id desc");

    条件查询:

    按位置绑定参数Query query = session.createQuery("from Customer where cust_name = ?");
         query.setParameter(0, "
    小军军");

    按名称绑定参数Query query= session.createQuery("from Customer where cust_name = :name");
         query.setParameter("name", "
    小添添");

    分页查询:

    Query query = session.createQuery("from LinkMan order by lkm_id desc");
    query.setFirstResult(5);
    query.setMaxResults(5);

    统计查询:

    Query query = session.createQuery("select count(*) from Customer");
    Long num = (Long) query.uniqueResult();

    投影查询:

    查询一列(一个字段)

    List<String> list = session.createQuery("select cust_name from
    Customer").list();

    查询多列 (多个字段)

    List<Object[]> list = session.createQuery("select cust_id,cust_name from
    Customer").list();

    构造方式查询(查询并封装对象)

    //封装函数要有对应的构造函数 而且参数顺序不可乱

    List<Customer> list = session.createQuery("select new
    Customer(cust_id,cust_name) from Customer").list();

     

  6. QBC 检索方式

    检索方式:

    基本查询:

    Criteria criteria=session.createCriteria(Customer.class);

    List<Customer> list = criteria.list();

    条件查询:

    //创建查询容器

    Criteria criteria=session.createCriteria(Customer.class);

    //创建查询条件

    Criterion criterion=Restrictions.eq("cust_name", "慢慢");

    //添加查询条件进入到容器

    criteria.add(criterion);

    List<Customer> list=criteria.list();

    分页查询:

    criterion.setFirstResult(1);

    criterion.setMaxResults(5);

    排序查询:

    criteria.addOrder(Order.desc("cust_id"));

    统计查询:

    criteria.setProjection(Projections.rowCount());

    long count=(long)criteria.uniqueResult();

    离线条件检索:

    //离线查询DetachedCriteria类是一个脱离session的查询容器

            //可以再其他的层对条件进行过滤封装

    //最后到了dao层在与session绑定

    创建DetachedCriteria

    DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Customer.class);

    绑定条件这里可以判断非空

    detachedCriteria.add(Restrictions.eq("cust_name", "慢慢"));

    添加session关联

    Criteria criteria = detachedCriteria.getExecutableCriteria(session);

    List<Customer> list = criteria.list();

     

  7. SQL 检索方式

    SQLQuery sqlQuery=session.createSQLQuery("select c.cust_id from cst_customer c");

     

    Hibernate的多表关系

    1. 简介

    多表的关系在数据库中是表与表之间的关联,而在hibernate中,用对象的思想对其进行了描述,在hibernate中的关系,主要靠实体类的包含,和,映射文件的描述

    2. 一对多1里放集合)(&里放对象)

  • 2.1 实体类中关系的实现:

 

1—>&(一对多的一方)

在(一)的一方的实体类中放入(多)的一方的对象集合 以表示(一)的一方有多个(多)的对象

&—>1(多对一的一方)

在(多)的一方的实体类中放入(一)的一方的一个对象 以表示(多)的一方只对应一个(一)的一方

  • 2.2 映射文件中关系的描述

1—>&

<setname=""><!-- 因为一的一方包含多的一方的集合 所有配置文件以集合作标签 name表示集合的名字 -->

     <keycolumn=""/><!--key标签的 column表示外键的名称 -->

     <one-to-manyclass=""/><!--一对多 class 表示多的一方的实体类的全限定名-->

</set>

&—>1

因为在多的一方包含一个多的对象,直接用关系标签,再用三个属性指定,对象名、外键和位置

<many-to-onename=""class=""column=""/>

  • 2.3 入门测试

    //创建一的对象

    Customer customer1=new Customer("李总");

    //创建多的对象

    Linkmanl1=new Linkman("李密");

    Linkmanl2=new Linkman("王密");

    //往一的一方添加多的对象 创建关系

    customer1.getLinkmans().add(l1);

    customer1.getLinkmans().add(l2);

    //往多的一方添加一的对象 创建关系

    l1.setCustomer(customer1);

    l2.setCustomer(customer1);

    //保存

    session.save(customer1);

    session.save(l1);

    session.save(l2);

3. 多对多(彼此往里放集合)

  • 3.1 实体类中关系的实现

在彼此的实体类中加入包含彼此对象的集合

  • 3.2 映射文件中关系的描述

    <!-- 配置关联映射

            name属性:对方的集合的属性名称

            table属性:中间表表名

        -->

        <setname=""table="">

            <!-- column:自己在中间表中的外键名称-->

            <keycolumn="role_no"/>

            

            <!--

                class属性:对方的全限定名

                column属性:对方在中间表中的外键名称

             -->

            <many-to-manyclass=""column=""/>

        </set>

注意:

            开发中让被动方放弃外键维护权

            在角色的set标签上配置inverse="true"

  • 3.3 入门测试

    //创建两个用户

        User u1 = new User();

        u1.setUser_name("曼曼");

        Useru2 = new User();

        u2.setUser_name("小小");

        //创建3个角色

        Roler1 = new Role();

        r1.setRole_name("员工");

        Roler2 = new Role();

        r2.setRole_name("助教");

        Roler3 = new Role();

        r3.setRole_name("讲师");

        //双向关联

        u1.getRoles().add(r1);

        u1.getRoles().add(r2);

        u2.getRoles().add(r1);

        u2.getRoles().add(r3);

        

        r1.getUsers().add(u1);

        r1.getUsers().add(u2);

        r2.getUsers().add(u1);

        r3.getUsers().add(u2);

        //保存

        session.save(u1);

        session.save(u2);

        session.save(r1);

        session.save(r2);

        session.save(r3);

4. 级联:(牵一发而动全身)

级联是有方向性的,也就是你动谁,谁就是主体,在主体的映射文件中配置对象关系的标签最外层加cascade=""属性 里边的值是你要做什么操作,多个操作中间用,隔开

例:

保存或更新(值save-update

级联保存或更新

保存客户的同时,也保存关联的联系人

客户是主体,在主体的映射文件中配置级联保存更新 set标签配置 cascade=

"save-update"

保存联系人的同时,也保存关联的联系人

联系人是主体,在主体的映射文件中配置级联保存更新 many-to-one标签配置cascade="save-update"

 

删除(值delete

级联删除:(删一个全删)

删除客户的同时,也删除他的联系人(先查询)

客户是主体,需要在客户的映射文件中配置级联删除cascade="delete"

删除联系人时也删除对应的客户

联系人是主体,在联系人的映射配置文件中配置级联删除

默认删除:(删除1的时候置&为null)

删除一的一方的记录时:会先把多表中关联的记录的外键置为null,在删除

一表中的数据,商品(多)一方 无分类 , 分类(一)一方 删除

在多表中,谁是主体配置谁,操作谁,谁就是主体

 

5. 冗余sql(多余sql

解决方法:

方案1:单向关联

方案2:让其中一方放弃外键维护权 (让一的一方放弃外键维护权) 在set标签上配置 inverse="true"

 

Hibernate中的多表查询

内连接、

隐式内连接:

显式内连接:

☆迫切内连接:

迫切就是将每一条记录都封装成一个对象

使用:在jion后边加上fetch

* 迫切内连接就是把查询到的所有客户的信息都封存到了每个对应的Customer对象中 联系人的信息封存到了Customer的集合中

         * 内连接是每用到一个客户的信息 发送一次sql 迫切内链接 是一次全查了

         *

         * 迫切内连接要去重查询 distinct

 

外链接

左外连接

右外链接

迫切左外连接

Hibernate的优化

  • 1. 延迟加载

     *         他决定什么时候发送sql语句

     *         1.1类级别的延迟加载

     *             获取一个对象的时候是否采用延迟加载

     *             关闭类级别的延迟加载

     *                 1.在持久化类上使用final修饰

     *                 2.在配置文件中修改 class标签上 lazy=false

     *         1.2关联级别的延迟加载

     *             通过一个对象获取其关联对象的时候是否采用延迟加载

     *             通过lazy属性配

     *                 在set标签上配置

     *                     true:使用延迟加载 默认值

     *                     false:不使用延迟加载

     *                     extra:及其懒惰的

     *                 在many-to-one上配置

     *                     false:不使用延迟加载

*                     proxy:代理 默认值 (决定于1的一方)

  • 2. 抓取策略(查询关联对象的时候,用什么sql格式)

    决定的是 sql的格式

    通过fetch属性配置

    2.1在set标签上配置

    Select:发送普通的查询语句

    Join:发送一条迫切左外连接语句 lazy失效了

    Subselect:发送一条子查询语句

    2.2在many-to-one

    Select:发送普通的查询语句

    Join:发送一条迫切左外连接语句 lazy失效了

 

  • 3. 批量抓取    

作用:    (一次查询几个)

        查询多个对象的多个关联对象产生的n+1问题

        查询所有客户及其联系人的名称

            在set标签上配置 batch-size=int

                一次查询几个客户的联系人

        查询联系人名称及其客户的名称

在一的一方的class标签上配置batch-size=int

    一次查询几个客户

 

持久化类

  1. 简介

    一个类可以持久化到数据库中就是持久化类,就是一个javabean有了映射文件(就是javaBean)

    持久化类编写规范:

        1.必须是一个公共的具体的类

    2.字段必须私有,必须提供公共的访问方法

    3.必须有一个无参构造器

    4.必须有一个属性(OID)和主键字段对应

    5.尽量使用包装类修饰字段(包装类有null,基本类型为0)

    6.尽量不要使用final修饰类 因为不能继承 许多功能就失效了

  2. 持久化对象的三种状态

    1.瞬时态:没有oid且没有与session关联     (刚创建对象)

    2.持久态:有oid且和session关联            (session加入缓存操作的过程)

    3.托管态:有oid且和session失去关联,与数据库产生关联    (保存之后)

    注意:

    持久化对象可以自动更新数据库 (依赖于一级缓存)

    例如 session.get 获取之后 通过set修改

    一级缓存

    缓存:介于程序和硬件之间的一种介质

    作用:减少对硬件的访问

     

    ☆一级缓存:是hibernate自带的,不能卸载的。Session的生命周期和一级缓存的生命周期一样,所以也称之为是session级别的的缓存

    二级缓存:不是hibernate自带的,用的时候(chcache),需要导入jar包,还需要配置文件等等一系列操作,一般使用redis代替

     

    一级缓存依赖的或者说本质就是一系列集合

    一级缓存可以分为两部分(缓存区和快照区)

    放入一级缓存的时候,会将数据放入缓存区一份,也会放入快照区一份,快照区就是方放入缓存区的状态

     

    操作的过程中只操作缓存区

    当事物提交的时候对比缓存区和快照区是否一致

    一致:啥也不操作

    不一致:马上发送update语句

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值