zoukankan      html  css  js  c++  java
  • Hibernate框架(未完待续······)

     

            作为SSH三大框架之一的Hibernate,是用来把程序的Dao层和数据库打交道用的,它封装了JDBC的步骤,是我们对数据库的操作更加简单,更加快捷。利用Hibernate框架我们就可以不再编写重复的JDBC代码,不再反复的测试我们的SQL语句写的如何。这里这需要我们简单配置,调用框架给我们提供的方法,就可以完成对数据增删改查的,那么Hibernate到底是个什么样的框架呢?如何使用呢?先看一个关于Hibernate框架的知识体系图:

    Hibernate有什么好处?

        一、Hibernate是JDBC的轻量级的对象封装,它是一个独立的对象持久层框架,和App Server,和EJB没有什么必然的联系。Hibernate可以用在任何JDBC可以使用的场合,例如Java应用程序的数据库访问代码,DAO接口的实现类,甚至可以是BMP里面的访问数据库的代码。从这个意义上来说,Hibernate和EB不是一个范畴的东西,也不存在非此即彼的关系。


    二、Hibernate是一个和JDBC密切关联的框架,所以Hibernate的兼容性和JDBC驱动,和数据库都有一定的关系,但是和使用它的Java程序,和App Server没有任何关系,也不存在兼容性问题。

    三、Hibernate不能用来直接和Entity Bean做对比,只有放在整个J2EE项目的框架中才能比较。并且即使是放在软件整体框架中来看,Hibernate也是做为JDBC的替代者出现的,而不是Entity Bean的替代者出现的,让我再列一次我已经列n次的框架结构:

    传统的架构:
    1) Session Bean <-> Entity Bean <-> DB
    为了解决性能障碍的替代架构:
    2) Session Bean <-> DAO <-> JDBC <-> DB
    使用Hibernate来提高上面架构的开发效率的架构:
    3) Session Bean <-> DAO <-> Hibernate <-> DB 

    就上面3个架构来分析:
    1、内存消耗:采用JDBC的架构2无疑是最省内存的,Hibernate的架构3次之,EB的架构1最差。

    2、运行效率:如果JDBC的代码写的非常优化,那么JDBC架构运行效率最高,但是实际项目中,这一点几乎做不到,这需要程序员非常精通JDBC,运用Batch语句,调整PreapredStatement的Batch Size和Fetch Size等参数,以及在必要的情况下采用结果集cache等等。而一般情况下程序员是做不到这一点的。因此Hibernate架构表现出最快的运行效率。EB的架构效率会差的很远。

    3、开发效率:在有JBuilder的支持下以及简单的项目,EB架构开发效率最高,JDBC次之,Hibernate最差。但是在大的项目,特别是持久层关系映射很复杂的情况下,Hibernate效率高的惊人,JDBC次之,而EB架构很可能会失败。

    4、分布式,安全检查,集群,负载均衡的支持
    由于有SB做为Facade,3个架构没有区别。

    四、EB和Hibernate学习难度在哪里?

    EB的难度在哪里?不在复杂的XML配置文件上,而在于EB运用稍微不慎,就有严重的性能障碍。所以难在你需要学习很多EJB设计模式来避开性能问题,需要学习App Server和EB的配置来优化EB的运行效率。做EB的开发工作,程序员的大部分精力都被放到了EB的性能问题上了,反而没有更多的精力关注本身就主要投入精力去考虑的对象持久层的设计上来。

    Hibernate难在哪里?不在Hibernate本身的复杂,实际上Hibernate非常的简单,难在Hibernate太灵活了。

    当你用EB来实现持久层的时候,你会发现EB实在是太笨拙了,笨拙到你根本没有什么可以选择的余地,所以你根本就不用花费精力去设计方案,去平衡方案的好坏,去费脑筋考虑选择哪个方案,因为只有唯一的方案摆在你面前,你只能这么做,没得选择。

    Hibernate相反,它太灵活了,相同的问题,你至少可以设计出十几种方案来解决,所以特别的犯难,究竟用这个,还是用那个呢?这些方案之间到底有什么区别呢?他们的运行原理有什么不同?运行效率哪个比较好?光是主键生成,就有七八种方案供你选择,你为难不为难?集合属性可以用Set,可以用List,还可以用Bag,到底哪个效率高,你为难不为难?查询可以用iterator,可以用list,哪个好,有什么区别?你为难不为难?复合主键你可以直接在hbm里面配置,也可以自定义CustomerType,哪种比较好些?你为难不为难?对于一个表,你可以选择单一映射一个对象,也可以映射成父子对象,还可以映射成两个1:1的对象,在什么情况下用哪种方案比较好,你为难不为难?

    这个列表可以一直开列下去,直到你不想再看下去为止。当你面前摆着无数的眼花缭乱的方案的时候,你会觉得幸福呢?还是悲哀呢?如果你是一个负责的程序员,那么你一定会仔细研究每种方案的区别,每种方案的效率,每种方案的适用场合,你会觉得你已经陷入进去拔不出来了。如果是用EB,你第一秒种就已经做出了决定,根本没得选择,比如说集合属性,你只能用Collection,如果是Hibernate,你会在Bag,List和Set之间来回犹豫不决,甚至搞不清楚的话,程序都没有办法写。

    Hibernate的核心组件
    在基于MVC设计模式的JAVA WEB应用中,Hibernate可以作为模型层/数据访问层。它通过配置文件(hibernate.properties或hibernate.cfg.xml)和映射文件(***.hbm.xml)把JAVA对象或PO(Persistent Object,持久化对象)映射到数据库中的数据库,然后通过操作PO,对数据表中的数据进行增,删,改,查等操作。
    除配置文件,映射文件和持久化类外,Hibernate的核心组件包括以下几部分:
    a)Configuration类:用来读取Hibernate配置文件,并生成SessionFactory对象。
    b)SessionFactory接口:产生Session实例工厂。
    c)Session接口:用来操作PO。它有get(),load(),save(),update()和delete()等方法用来对PO进行加载,保存,更新及删除等操作。它是Hibernate的核心接口。
    d)Query接口:用来对PO进行查询操。它可以从Session的createQuery()方法生成。
    e)Transaction接口:用来管理Hibernate事务,它主要方法有commit()和rollback(),可以从Session的beginTrancation()方法生成。

    Persistent Object
    持久化对象可以是普通的Javabeans,惟一特殊的是它们与(仅一个)Session相关联。JavaBeans在Hibernate中存在三种状态:
    1.临时状态(transient):当一个JavaBean对象在内存中孤立存在,不与数据库中的数据有任何关联关系时,那么这个JavaBeans对象就称为临时对象(Transient Object)。
    2.持久化状态(persistent):当一个JavaBean对象与一个Session相关联时,就变成持久化对象(Persistent Object)
    3.脱管状态(detached):在这个Session被关闭的同时,这个对象也会脱离持久化状态,就变成脱管状态(Detached Object),可以被应用程序的任何层自由使用,例如可以做与表示层打交道的数据舆对象(Data Transfer Object)。

    Hibernate的运行过程
    Hibernate的运行过程如下:

    A:应用程序先调用Configration类,该类读取Hibernate的配置文件及映射文件中的信息,并用这些信息生成一个SessionFactpry对象。
    B:然后从SessionFactory对象生成一个Session对象,并用Session对象生成Transaction对象;可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载,保存,更新,删除等操作;在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将 提交这些操作结果到数据库中。

    Hibernate到底是什么?

                      Hibernate是一个基于元数据轻量级ORM框架:

                     1,元数据(Meta Data:data about data(数据的数据),也就是说描述一个对象数据,相当于这个对象的上下文环境。

                     2,轻量级:占用资源少,没有侵入性。(其实我认为这只是相对而言,如果和Ibatis相比,它到成重量级的了)。

                     3ORM:(Object Relation Mapping)对象关系数据库的映射

                         这是Hibernate框架的重点,也就是说将我们程序中的实体(bean,这里也叫POJO)和数据库中的表进行映射。java类型和sql类型映射,面向对象设计和关系型数据库设计的映射,从而我们只需要将更多的精力放到业务中,而不是sql数据库方面。

                    4POJO:(Plain Ordinary Java Object,无格式的普通java对象,也就是上边说的实体,和数据库做映射的简单类。只是在这里提出了一个新的名词而已。

                总而言之,Hibernate就是将我们的数据库表和程序的POJO类进行映射,数据的操作进行了封装,使我们不用把数据库弄得非常精通,我们会面向对象编程就可以了,这样大大提高了我们的编程效率,而且对个人的知识要求也降低了。(Hibernate的设计目的是这样的,可是我觉的要想更好的应用Hibernate,更好的掌握开发的来龙去脉,这是要求我们要有更高的能力了,知其然知其所以然了)

                二,环境搭建:

       1,和前边几个框架的大概流程一样,首先需要我们拷入必备的jar包。jar包的拷入奔着一个够用即可的原则,用什么拷贝什么,当然有些日志输出,单元测试是为了更好的观察框架而拷入的不是必备的。这里讲到是用MySql来进行演示,所以使用了mysql的驱动jar包:

     antlr-2.7.6.jar (生成SQL语句)

    asm.jar(字节码增强工具类)

    c3p0-0.9.1.jar(数据源连接池组件)

    cglib-2.1.3.jar(代理组件,基于继承的)

    commons-collections-2.1.1.jar(集合工具类组件,会进行高效的操作)

    commons-logging-1.0.4.jar(日志输出的转换组件)

    log4j-1.2.11.jar(日志输出组件,更加详细和可以控制输出格式,及目的地)

    dom4j-1.6.1.jar(XML解析)

    ehcache-1.2.3.jar(缓存组件)

    ejb3-persistence.jar(持久化操作的规范jar包)

    hibernate3.jar(框架的核心jar包)

    jta.jar(全局的事务管理)

    junit-3.8.1.jar        (单元测试)                        

    mysql-connector-java-3.1.13-bin.jar        (MySQL数据库驱动jar包)

      2,引入配置文件:

          hibernate.cfg.xml  Hibernate核心配置文件(包括数据库的连接配置,映射文件的读取等)

          log4j.properties          Log4j的日志输出控制文件

          User.hbm.xml  映射文件(这里的User只是匹配User实体的,一个实体类对应一个此类的映射文件。)

    Hibernate包目录结构

    我用的Hibernate版本是3.6.10 ,引入的库有如下11

     Hibernate的运行过程如下图:

    核心配置文件:Hibernate.cfg.xml的编写代码如下

     1 <!-- 我分别来写MySQL 与 Oracle 的   下面,先写MySQL的--> 
     2 <hibernate-configuration>  
     3     <!-- 构造数据库的连接工厂,这是Hibernate的核心类 -->  
     4     <session-factory>  
     5       
     6         <!-- 这里是简单的数据库连接的基本信息,也可以写在配置文件中,或者利用JNDI来调用数据源 -->  
     7         <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/example?useUnicode=true&characterEncoding=utf8</property>  
     8         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
     9         <property name="hibernate.connection.username">sm</property>  
    10         <property name="hibernate.connection.password">1</property>  
    11           
    12         <!-- 在控制台里打印生成的SQL语句 -->  
    13         <property name="hibernate.show_sql">true</property>  
    14         <!-- 格式化控制台输出的SQL语句,这两条都是方便我们来学习Hibernate框架 -->  
    15         <property name="hibernate.format_sql">true</property>  
    16           
    17           
    18         <!--   
    19             方言:根据指定的方言与数据库打交道,完成SQL的具有语句生成,因为不同的数据库sql语法还是有区别的,  
    20             这里相当于告诉Hibernate框架,我们使用的是什么数据库。  
    21                 MySQL : org.hibernate.dialect.MySQLDialect  
    22                 Oracle : org.hibernate.dialect.OracleDialect  
    23          -->  
    24         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
    25           
    26         <!-- 管理所有的映射资源文件,这里仅仅配置了User类的配置映射文件,应该将我们的所有的映射配置文件设置到这里,这样我们框架才能找到 -->  
    27         <mapping resource="com/ljh/hibernate/pojo/User.hbm.xml"/>  
    28           
    29     </session-factory>  
    30 </hibernate-configuration>  
    31 
    32 
    33 
    34 <!--然后下面这是Orcale的-->
    35 <?xml version='1.0' encoding='utf-8'?>
    36 <!DOCTYPE hibernate-configuration PUBLIC
    37         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    38         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    39 
    40 <hibernate-configuration>
    41 
    42     <session-factory>
    43 
    44         <!-- Database connection settings -->
    45         <property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
    46         <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
    47         <property name="connection.username">sm</property>
    48         <property name="connection.password">1</property>
    49 
    50         <!-- JDBC connection pool (use the built-in) -->
    51         <!-- <property name="connection.pool_size">1</property> -->
    52 
    53         <!-- SQL dialect -->
    54         <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
    55 
    56         <!-- Echo all executed SQL to stdout -->
    57         <property name="show_sql">true</property>
    58 
    59         <!-- Drop and re-create the database schema on startup -->
    60         <property name="format_sql">true</property>
    61 
    62         <mapping class="cn.sm.entity.Student" />
    63         
    64 
    65     </session-factory>
    66 
    67 </hibernate-configuration>

    然后准备Student实体类

     1 package cn.sm.entity;
     2 //学生实体类
     3 public class Student {
     4     
     5     private int stuno;
     6     
     7     private String stuname;
     8     
     9     private int stuage;
    10     
    11     private int stuid;
    12     
    13     private int stuseat;
    14 
    15     public Student() {
    16         super();
    17     }
    18 
    19     public Student(String stuname, int stuage, int stuid, int stuseat) {
    20         super();
    21         this.stuname = stuname;
    22         this.stuage = stuage;
    23         this.stuid = stuid;
    24         this.stuseat = stuseat;
    25     }
    26 
    27     public Student(int stuno, String stuname, int stuage, int stuid, int stuseat) {
    28         super();
    29         this.stuno = stuno;
    30         this.stuname = stuname;
    31         this.stuage = stuage;
    32         this.stuid = stuid;
    33         this.stuseat = stuseat;
    34     }
    35 
    36 
    37     public int getStuid() {
    38         return stuid;
    39     }
    40     
    41     public void setStuid(int stuid) {
    42         this.stuid = stuid;
    43     }
    44 
    45 
    46 
    47     public int getStuseat() {
    48         return stuseat;
    49     }
    50 
    51 
    52 
    53     public void setStuseat(int stuseat) {
    54         this.stuseat = stuseat;
    55     }
    56 
    57 
    58 
    59     public int getStuno() {
    60         return stuno;
    61     }
    62 
    63     public void setStuno(int stuno) {
    64         this.stuno = stuno;
    65     }
    66 
    67     public String getStuname() {
    68         return stuname;
    69     }
    70 
    71     public void setStuname(String stuname) {
    72         this.stuname = stuname;
    73     }
    74 
    75     public int getStuage() {
    76         return stuage;
    77     }
    78 
    79     public void setStuage(int stuage) {
    80         this.stuage = stuage;
    81     }
    82 
    83     
    84 }

    在实体类下设计映射文件Student.hbm.xml(在配置文件hibernate.cfg.xml使用)

     1 <?xml version="1.0"?>
     2 <!DOCTYPE hibernate-mapping PUBLIC
     3         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
     4         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
     5 
     6     <hibernate-mapping package="cn.zhang.entity">
     7         <class name="Student" table="stuinfo">
     8         <id name="stuno" column="stuno">
     9            <!-- 主键生成策略:native:
    10            native:如果后台是Oracle  
    11                       后台是MySQL,自动应用自增 -->
    12             <generator class="native"/>
    13         </id>
    14         <property name="stuname" type="string" column="stuname"/>
    15         <property name="stuage"/>
    16         
    17         <property name="stuid" type="int" column="stuid"/>
    18         <property name="stuseat"/>
    19     </class>
    20        
    21 </hibernate-mapping>

    新增一名学生

     1 package cn.sm.test;
     2 //新增一条数据
     3 import org.hibernate.SessionFactory;
     4 import org.hibernate.Transaction;
     5 import org.hibernate.cfg.Configuration;
     6 import org.hibernate.classic.Session;
     7 
     8 import cn.sm.entity.Student;
     9 
    10 public class InsertTest {
    11     
    12     public static void main(String[] args) {
    13         //准备对象
    14         Student student=new Student("云云", 12,112333,2);//Student.hbm.xml已配置编号为自增,所以这里不用添加编号了
    15          //读取大配置文件,获取要连接的数据库信息
    16         Configuration configuration=new Configuration().configure();
    17          //创建SessionFactory
    18         SessionFactory factory = configuration.buildSessionFactory();
    19         //加工session
    20         Session openSession = factory.openSession();
    21         
    22         Transaction beginTransaction = openSession.beginTransaction();
    23         openSession.save(student);
    24         
    25         beginTransaction.commit();
    26         
    27         System.out.println("成成成成成功!");
    28 
    29     }
    30 
    31 }

    修改一名学生信息

     1 package cn.sm.test;
     2 import org.hibernate.SessionFactory;
     3 import org.hibernate.Transaction;
     4 import org.hibernate.cfg.Configuration;
     5 import org.hibernate.classic.Session;
     6 
     7 import cn.sm.entity.Student;
     8 
     9 public class UpdateTest {
    10 
    11     /**
    12      * @param args
    13      */
    14     public static void main(String[] args) {
    15         //1.读取大配置文件,获取要连接的数据库信息
    16         Configuration conf=new Configuration().configure();
    17         //2.创建SessionFactory
    18         SessionFactory factory =conf.buildSessionFactory();
    19         //3加工session
    20         Session session = factory.openSession();
    21         Transaction tx=session.beginTransaction();
    22         //获取对象
    23         Student stu =new Student(1,"云云", 12,112333,2);
    24         //更新
    25         session.update(stu);
    26         //提交事务
    27         tx.commit();
    28         System.out.println("更新成成成成成功");
    29 
    30 
    31     }
    32 
    33 }

    删除一名指定学生信息

    package cn.sm.test;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.classic.Session;
    
    import cn.sm.entity.Student;
    public class DeleteTest {
        
        public static void main(String[] args) {
            //1.读取大配置文件,获取要连接的数据库信息
            Configuration conf=new Configuration().configure();
            //2.创建SessionFactory
            SessionFactory factory =conf.buildSessionFactory();
            //3.加工session
            Session session = factory.openSession();
            
            Transaction tx=session.beginTransaction();
            //获取对象
            Student stu =new Student();
            stu.setStuno(3);//指定要删除的编号
            //删除指定
            session.delete(stu);
            //提交事务
            tx.commit();
            System.out.println("删除成成成成成功");
    
        }
    
    }

    查询一名指定学生信息

     1 package cn.sm.test;
     2 
     3 import org.hibernate.SessionFactory;
     4 import org.hibernate.cfg.Configuration;
     5 import org.hibernate.classic.Session;
     6 
     7 import cn.sm.entity.Student;
     8 
     9 public class SelectTest {
    10 
    11     public static void main(String[] args) {
    12         //1.读取大配置文件,获取要连接的数据库信息
    13         Configuration conf=new Configuration().configure();
    14         //2.创建SessionFactory
    15         SessionFactory factory =conf.buildSessionFactory();
    16         //3.打开session
    17         Session session = factory.openSession();
    18         //4.加载数据操作
    19            //如果表中没有你指定的主键列,get()方法的是null
    20         Student student =(Student)session.get(Student.class, 4); 
    21            //如果表中没有你指定的主键列,程序运行到student.getStuname()时会抛出异常
    22        //Student student =(Student)session.load(Student.class, 4);
    23         //5.输出数据
    24         System.out.println(student.getStuname());
    25         //6.关闭session
    26         session.close();
    27         
    28         
    29 
    30     }
    31 
    32 }

    根据上面的信息,我想你应该对HIberiannate 已经有所了解了 , 敬请期待更多内容的补充!  感谢有你!

  • 相关阅读:
    HDU 4864 Task(贪心值得学习)
    使程序在Linux下后台运行
    KMP算法
    优先队列的使用
    POJ 2761 Feed the dogs(树状数组求区间第K大)
    HDU 3584 Cube (三维树状数组)
    HDU 1892 See you~ (二维树状数组)
    POJ 1195 Mobile phones(二维树状数组)
    HDU 1166 敌兵布阵 (树状数组和线段树解法)
    POj 1703 Find them, Catch them(关系并查集)
  • 原文地址:https://www.cnblogs.com/smbk/p/5759849.html
Copyright © 2011-2022 走看看