你的位置:首页 > Java教程

[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的难度在哪里?不在复杂的
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.
除配置文件,映射文件和持久化类外,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相比,它到成重量级的了)。

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

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

                4,POJO:(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(

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.Hibernate核心配置文件(包括数据库的连接配置,映射文件的读取等)

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

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

Hibernate包目录结构

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

 

 Hibernate的运行过程如下图:

核心配置文件:Hibernate.cfg.

 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./> 28      29   </session-factory> 30 </hibernate-configuration> 31 32 33 34 <!--然后下面这是Orcale的-->35 <??>36 <!DOCTYPE hibernate-configuration PUBLIC37     "-//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.

 1 <??> 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.15     //读取大配置文件,获取要连接的数据库信息16     Configuration configuration=new Configuration().configure();17     //创建SessionFactory18     SessionFactory factory = configuration.buildSessionFactory();19     //加工session20     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 args13   */14   public static void main(String[] args) {15     //1.读取大配置文件,获取要连接的数据库信息16     Configuration conf=new Configuration().configure();17     //2.创建SessionFactory18     SessionFactory factory =conf.buildSessionFactory();19     //3加工session20     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.创建SessionFactory15     SessionFactory factory =conf.buildSessionFactory();16     //3.打开session17     Session session = factory.openSession();18     //4.加载数据操作19      //如果表中没有你指定的主键列,get()方法的是null20     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.关闭session26     session.close();27     28     29 30   }31 32 }

 

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