⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 09. hibernate note.txt

📁 在达内培训java笔记
💻 TXT
📖 第 1 页 / 共 2 页
字号:

软件开发的分层思想:
    三层架构:
                           数据表现层     业务逻辑层      数据持久层
        SUN的桌面应用        Swing AWT    普通Java类     JDBC
        SUN的WEB基本应用     JSP          普通Servlet    JDBC
        SUN的WEB高级应用     JSF          SessionBean   Persistence 
        WEB国内流行开源      Struts       Spring         Hibernate


一、 对象持久化的理论
    1.对象持久化:内存中的对象转存到外部持久设备上,在需要的时候还可以恢复。
    2.对象持久化的原因(目标):
      物理: 1) 内存不能持久,需要在硬盘上持久保存 //(物理上,物理的都不是根本原因) 
            2) 内存容量有限,需要在容量更大的硬盘上保存 
      应用: 3) 共享(Internet的本质:信息的收集、整理、发布) //最重要的原因
            4) 检索(大规模) //也很重要
            5) 管理(备份、安全) 
    3.怎样进行对象持久化?(仅从JAVA方面讲) 
      物理: 1) 对象序列化
            2) DB技术(JDBC 数据库) 
    4.怎样利用数据库做对象持久化?
            1) JDBC 
               优点:功能完备、理论上效率高
               缺点:复杂(难)、代码量大、面向R(过程;二维表关系) 
            2) EJB 仅讲Entity Bean
               优点:封装JDBC
               缺点:更复杂的API、重量级(侵入式)、功能不完备、难共享
                    缺点的后果:开发周期长、测试困难、面向过程
               以上是 2.0之前的版本,但 3.0跟Hibernate基本一样
            3) ORM 轻量级框架(Hibernate) 
               现阶段最佳的持久化工具:文档齐全、服务很好、工业标准、大量应用、易学
               优点:封装JBDC、简单的API、轻量级(只做持久化)(用类库)、PO(持久对象)->POJO(纯JAVA)、开源
               缺点:不够JDBC灵活
    5.结论:
      1)对象持久化是必须的
      2)必须使用DB来实现
      3)Hibernate必须的(现阶段最佳选择) 
          开源工具的通常问题:1.文档不全;2.服务不全;3.标准化不够
          而Hibernate避免了所有这些问题 

二、 ORM和Hibernate的相关知识(理解)
    1) ORM:Object Relational Mapping
       对象-关系映射实现了面向对象世界中对象到关系数据库中的表的自动的(和透明的)持久化,
       使用元数据(meta data)描述对象与数据库间的映射。
    2) Hibernate是非常优秀、成熟的O/R Mapping框架。它提供了强大的对象和关系数据库映射以及查询功能。

    规范:
        1.一个映射文件对应一个持久类(一一对应) 
        2.映射文件的名字和它所描述的持久类的名字保持一致
        3.映射文件应该与它所描述的类在同一包中
    po -> (pojo) 
       -> oid(唯一,中性) 
       -> getters/setters
       -> 构造方法


三、Hibernate核心API(理解)
    Configuration类:
        Configuration对象用于配置和启动Hibernate。Hibernate应用通过Configuration实例来指定对象-关系映射文
        件的位置或者动态配置Hibernate的属性,然后创建SessionFactory实例。
    SessionFactory接口:
        一个SessionFactory实例对应一个数据存储源。应用从SessionFactory中获取Session实例。
        1)它是线程安全的,这意味着它的一个实例能够被应用的多个线程共享。
        2)它是重量级的,这意味着不能随意创建或者销毁,一个数据库只对应一个SessionFactory。
          通常构建SessionFactory是在某对象Bean的静态初始化代码块中进行。
          如果应用只是访问一个数据库,只需创建一个SessionFactory实例,并且在应用初始化的时候创建该实例。
          如果应用有同时访问多个数据库,则需为每个数据库创建一个单独的SessionFactory。
    Session接口:
        是Hibernate应用最广泛的接口。它提供了和持久化相关的操作,如添加,删除,更改,加载和查询对象。
        1)它是线程不安全的,因此在设计软件架构时,应尽量避免多个线程共享一个Session实例。
        2)Session实例是轻量级的,这意味着在程序可以经常创建和销毁Session对象,
          例如为每个客户请求分配单独的Session实例。
          原则:一个线程一个Session;一个事务一个Session。
    Transaction接口:
        是Hibernate的事务处理接口,它对底层的事务接口进行封装。
    Query和Criteria接口:
        这两个是Hibernate的查询接口,用于向数据库查询对象,以及控制执行查询的过程。
        Query实例包装了一个HQL查询语句。
        Criteria接口完全封装了基于字符串形式的查询语句,比Query接口更面向对象。Criteria更擅长于执行动态查询。
        补充:find方法也提供数据查询功能,但只是执行一些简单的HQL查询语句的快捷方式(已过时),远没有Query接口强大!


四、Hibernate开发步骤:(重点:必须掌握) 
   开始:(设置环境变量和配置) 
         在myeclipse里导入Hibernate的文件包(包括各数据库的驱动和其他的jar包,对版本敏感,注意各版本的兼容) 
         按hibernate规范编写名字为hibernate.cfg.xml文件(默认放在工程文件夹下) 
   步骤一:设计和建立数据库表
        可以用Hibernate直接生成映射表。
        Oracle里建表: create table t_ad (oid number(15) primary key,
                      ACTNO varchar(20) not null unique,BALANCE number(20));
   步骤二:持久化类的设计
     POJO----
     POJO 在Hibernate 语义中理解为数据库表所对应的Domain Object。(此类中只含有属性、构造方法、get/set方法) 
     这里的POJO就是所谓的“Plain Ordinary Java Object”,字面上来讲就是无格式普通Java 对象,
     简单的可以理解为一个不包含逻辑代码的值对象(Value Object 简称VO)。

   步骤三:持久化类和关系数据库的映射
     编写*.hbm.xml文件
     ---该文件配置持久化类和数据库表之间的映射关系
     <class name=“POJO的类全路径”  table=“对应的库表名”     //这两项一定要配置,其它的都可以不配置
			discriminator-value=“discriminator_value”   //区分不同子类的值,多态时使用。默认与类名一样
			dynamic-update=“true | false” //是否动态更新SQL。false:每次都更新所有属性;true:只更新修改的
			dynamic-insert=“true | false” //是否动态插入SQL。false:每次都插入所有属性;true:只插入非空的
			select-before-update=“true | false” //是否在update前查询对象是否被修改过,修改过才update
			polymorphism=“implicit | explicit”  //设置多态是显性(explicit)的还是隐性(implicit)的
			where=“查询时使用的SQL的条件子句”  //查询时使用的SQL的条件子句
			lazy=“true | false” //设置延迟加载策略
	 />
     一个实体对应一个xml文件,组件用id,非组件用property。
     *.hbm.xml文件样板:
        <?xml version="1.0"?>
        <!DOCTYPE hibernate-mapping PUBLIC 
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
        <hibernate-mapping package="com.tarena.ebank.biz.entity"><!--package指文件所在的包名 -->
           <class name="Account" table="student"><!-- name:POJO类的名; table数据库里对应的表名-->
              <id name="oid" column="OID"><!-- OID:(唯一,中性)表自动生成的(需要另外添加hilo表) -->
                 <generator class="hilo">
                    <param name="table">t_hi</param>
                    <param name="column">hi</param>
              </generator></id>
              <property name="actNo" column="ACTNO" unique="true" not-null="true"/>
              <property name="bal" column="BALANCE" not-null="true"/>
           </class>
        </hibernate-mapping>

   步骤四:Hibernate配置文件
     hibernate.cfg.xml或hibernate.properties
     1.需要配置那些信息:持久化映射,方言,特性,登陆信息
         多数使用默认的设置。
         A、dialect:方言,就是拼驱动程序和SQL语句。每种数据库对应一种方言。其实就是指定了用那一种数据库。
            Oracle数据库方言:org.hibernate.dialect.OracleDialect
            MySql数据库方言:org.hibernate.dialect.MySQLDialect
         B、Object Persistence:对象持久化。把内存中的数据保存到一个永久的介质中,比如说数据库。
         C、ORM:对象关系映射,是一个自动的过程
         注:持久对象与临时对象最大的区别是有没有数据库id标识。
    2.hibernate.cfg.xml的样板:
      <?xml version='1.0' encoding='UTF-8'?>
      <!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
      <hibernate-configuration>
      <session-factory>
            <!-- 数据库连接配置 -->
        <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">password</property>
            <!-- 自动建表语句:create覆盖旧表,update自动更新,none不理会 -->
        <property name="hbm2ddl.auto">update</property> 
            <!-- 是否在控制台上打印SQL(Hibernate把语句转化为SQL语句),默认false-->
        <property name="show_sql">true</property>
            <!-- 缓存策略,数据量不大可不写  -->
        <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="cache.use_query_cache">false</property>
        <property name="cache.use_second_level_cache">false</property>
            <!-- 不同数据库使用的SQL选择 -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="myeclipse.connection.profile">mysql</property>
            <!-- 连接池配置,练习时不写,使用默认的 -->
        <property name="connection.pool_size">1</property>
            <!--决定是采用thread或jta或自定义的方式来产生session,练习时不写,使用默认的  -->
        <property name="current_session_context_class">thread</property>
            <!-- *.hbm.xml文件路径,各关联表要一同写上 -->
        <mapping resource="many_to_one/vo/Customer.hbm.xml" />
        <mapping resource="com/tarena/ebank/biz/entity/Order.hbm.xml" />
      </session-factory>
      </hibernate-configuration>

    步骤五:使用Hibernate API
        //读取Hibernate.cfg.xml配置文件,并读到内存中为后续操作作准备
        Configuration config = new Configuration().configure();
        //SessionFactory缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。
        SessionFactory sessionFactory = config.buildSessionFactory();
        //Session是持久层操作的基础,相当于JDBC中的Connection。
        Session session = sessionFactory.openSession();

        try{  //为保持事务的原子性,必须捕捉异常。所有事务都放在这一代码块里。
            //操作事务时(增、删、改)必须显式的调用Transaction(默认:autoCommit=false)。
            Transaction tx = session.beginTransaction();
            for(int i=0; i<=1000; i++){
              Student stu = new Student(...);
              session.save(stu);//set value to stu
              //批量更新:为防止内存不足,分成每20个一批发送过去。 
              if(i%20==0){session.flush();session.clear();}//不是大批量更新,则不需要写这一行
              //默认时,会自动flush:查询之前、提交时。
            } tx.commit();//提交事务,Hibernate不喜欢抛异常,如有需要,自己捕捉。

            //查询方法。如果有必要,也可以用事务(调用Transaction) 
            String hql = "from Student s where s.stuNo like ? and s.Sal > ?";//Student是类而不是表
            List list = session.createQuery(hql)
                               .setString(0, "a00_").setDouble(1, 3000.0)//设置HQL的第一二个问号取值
                               .list();//Hibernate里面,没有返回值的都默认返回List
            StringBuffer sb = new StringBuffer();
            for(Student st :(List<Student>)list){//(List<Student>)强制类型转换
              sb.append(st.getOid()+"  "+st.getName()+"\n");//拿到Student类里的属性
            }System.out.print(sb.toString());//直接打印sb也可以,它也是调用toString,但这样写效率更高
        } catch (HibernateException e) {
            e.printStackTrace();
            session.getTransaction().rollback();//如果事务不成功,则rollback
        } finally {
            session.close();//注意关闭顺序,session先关,Factory最后关(因为它可以启动多个session) 
            sessionFactory.close();//关闭SessionFactory,虽然这里没看到它,但在HbnUtil里开启了。
        }


五、 Hibernate主键策略(上面的步骤三的一部分) 
    <id><generator class=“主键策略” /></id> 
    主键:在关系数据库中,主键用来标识记录并保证每条记录的唯一性(一般可保证全数据库唯一)。必须满足以下条件:
        1)不允许为空。
        2)不允许主键值重复。
        3)主键值不允许改变。
    1.自然主键:以有业务含义的字段为主键,称为自然主键。
        优点:不用额外的字段。
        缺点:当业务需求发生变化时,必须修改数据类型,修改表的主键,增加了维护数据库的难度。
    2.代理主键:增加一个额外的没有任何业务含义的一般被命名为ID的字段作为主键。
        缺点:增加了额外字段,占用部分存储空间。
        优点:提高了数据库设计的灵活性。
    Hibernate用对象标识(OID)来区分对象:
        Student stu = (Student)session.load(Student.class,101); //这代码加载了OID为101的Student对象
    Hibernate推荐使用代理主键,因此Hibernate的OID与代理主键对应,一般采用整数型,包括:short、int、long。

    1、主键生成策略: (Hibernate支持多种主键生成策略) 
    generator节点中class属性的值:
      1) assigned:assigned:由用户自定义ID,无需Hibernate或数据库参与。
         是<generator>元素没有指定时的默认生成策略。
           <id name="id" column="id"><generator class="assigned"/></id>
      2) hilo:通过hi/lo(高/低位)算法生成主键,需要另外建表保存主键生成的历史状态(这表只需要一个列和高位初始值)。
         hi/lo算法产生的标识只在一个特定的DB中是唯一的。所有数据库都可用。
         如果同一个数据库里多张表都需要用;可以建多张主键表,也可以共用同一字段,但最好是用同一张主键表的不同字段。
           <id name="id" column="id"><generator class="hilo">
               <param name="table">high_val</param><!--指定高位取值的表-->
               <param name="column">nextval</param> <!--指定高位取值的列-->
               <param name="max_lo">5</param><!--指定低位最大值,当取到最大值是会再取一个高位值再运算-->
           </generator></id>
      3) sequence:采用数据库提供的Sequence机制。
         Oracle,DB2等数据库都提供序列发生器生成主键,Hibernate也提供支持。
           <id name="id" column="id"><generator class="sequence">
               <param name="sequence">序列名</param>
           </generator></id>
      4) seqhilo:功能同hilo,只是自动建表保存高位值。主键生成的历史状态保存在Sequence中。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -