1.3 Hibernate
最初 SUN 公司推出了 Java EE 服务器端组件模型(EJB),但是由于 EJB 配置复杂,且适用范围较小,于是很快就被淘汰了。与 EJB 的失败伴随而来的是另外一个框架的应运而生。它就是从诞生至今都十分流行的 Hibernate。
Hibernate 一问世就成了 Java 世界首选的 ORM 模型,它是建立在 POJO 和数据库表模型的直接映射关系上的。
Hibernate 是建立在若干 POJO 通过 XML 映射文件(或注解)提供的规则映射到数据库表上的。换句话说,我们可以通过 POJO 直接操作数据库的数据。它提供的是一种全表映射的模型。如图 1-2 所示是 Hibernate 模型的开发过程。相对而言,Hibernate 对 JDBC 的封装程度还是比较高的,我们已经不需要编写 SQL 语言(Structured Query Language),只要使用 HQL 语言(Hibernate Query Langurage)就可以了。
图 1-2 Hibernate 模型的开发过程
首先我们需要提供 hbm.xml 文件,制定映射规则。下面以开发角色类为例进行讲解,如代码清单 1-2 所示。
代码清单 1-2:TRole.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- Generated 2015-12-12 22:50:58 by Hibernate Tools 4.3.1 --> <hibernate-mapping> <class name="com.learn.mybatis.chapter1.po.TRole" table="t_role" catalog="mybatis" optimistic-lock="version"> <id name="id" type="long"> <column name="id" /> <generator class="assigned" /> </id> <property name="roleName" type="string"> <column name="role_name" length="60" /> </property> <property name="note" type="string"> <column name="note" length="512" /> </property> </class> </hibernate-mapping>
这是一个简单的 XML 文件,它描述的是 POJO 和数据库表的映射关系。Hibernate 通过配置文件(或注解)就可以把数据库的数据直接映射到 POJO 上,我们可以通过操作 POJO 去操作数据库记录。对于不擅长 SQL 的程序员来说,这是莫大的惊喜,因为通过 Hibernate 你几乎不需要编写 SQL 就能操作数据库的记录。代码清单 1-3 是 Hibernate 的配置信息。
代码清单 1-3: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="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mybatis?zeroDateTimeBehavior=convertToNull</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">learn</property> <mapping resource="com/learn/mybatis/chapter1/po/TUser.hbm.xml"/> <mapping resource="com/learn/mybatis/chapter1/po/TRole.hbm.xml"/> </session-factory> </hibernate-configuration>
别看代码很多,但是全局就是这样的一个 XML 文件,作为数据库连接信息,配置信息也相对简易。然后建立 Hibernate 的工厂对象(SessionFactory),用它来做全局对象,产生 Session 接口,就可以操作数据库了,如代码清单 1-4 所示。
代码清单 1-4:HibernateUtil
public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { Configuration cfg = new Configuration().configure ("hibernate.cfg.xml"); sessionFactory = cfg.buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } }
上面的操作为的是产生 Hibernate 的 SessionFactroy。它作为全局,可以到处引用,那么剩下来的使用就非常简单了。比如我们可以用它来实现代码清单 1-1 的功能,如代码清单 1-5 所示。
代码清单 1-5:HibernateExample.java
public class HibernateExample { public static void main(String[] args) { Session session = null; try { session = HibernateUtil.getSessionFactory().openSession(); TRole role = (TRole)session.get(TRole.class, 1L); System.err.println("role_name = >" + role.getRoleName()); } finally { if (session != null) { session.close(); } } } }
按照代码清单 1-5 的方法来实现代码清单 1-1 的功能有以下好处:
消除了代码的映射规则,它全部被分离到了 XML 或者注解里面去配置。
无需再管理数据库连接,它也配置在 XML 里面。
一个会话中,不要操作多个对象,只要操作 Session 对象即可。
关闭资源只需要关闭一个 Session 便可。
这就是 Hibernate 的优势,在配置了映射文件和数据库连接文件后,Hibernate 就可以通过 Session 操作,非常容易,消除了 JDBC 带来的大量代码,大大提高了编程的简易性和可读性。此外,它还提供级联、缓存、映射、一对多等功能,以便我们使用。正因为具有这些优势,Hibernate 成为了时代的主流框架,被大量应用在各种 Java 数据库的访问中。Hibernate 是全表映射,你可以通过 HQL 去操作 POJO 进而操作数据库的数据。
但是 Hibernate 有缺陷吗?当然有,世界上没有完美无缺的方案。作为全表映射框架,举个例子来说,如果我们有张账务表(按年分表),比如 2015 年表命名为 bill2015,到了 2016 年表命名为 bill2016,要动态加映射关系,Hibernate 需要破坏底层封装才能做到。又比如说,一些账务信息往往需要和某些对象关联起来,不同的对象有不同的列,因此列名也是无法确定的,显然我们没有办法配置 XML 去完成映射规则。再者如果使用存储过程,Hibernate 也是无法适应的。这些都不是致命的,最为致命的问题是性能。Hibernate 屏蔽了 SQL,那就意味着只能全表映射,但是一张表可能有几十到上百个字段,而你感兴趣的只有 2 个,这是 Hibernate 无法适应的。尤其是在大型网站系统,对传输数据有严格规定,不能浪费带宽的场景下就更为明显了。有很复杂的场景需要关联多张表,Hibernate 全表逐级取对象的方法也只能作罢,写 SQL 还需要手工的映射取数据,这带来了很大的麻烦。此外,如果我们需要优化 SQL,Hibernate 也是无法做到的。
我们稍微总结一下 Hibernate 的缺点:
全表映射带来的不便,比如更新时需要发送所有的字段。
无法根据不同的条件组装不同的 SQL。
对多表关联和复杂 SQL 查询支持较差,需要自己写 SQL,返回后,需要自己将数据组装为 POJO。
不能有效支持存储过程。
虽然有 HQL,但是性能较差。大型互联网系统往往需要优化 SQL,而 Hibernate 做不到。
在当今大型互联网中,灵活、SQL 优化,减少数据的传递是最基本的优化方法,显然 Hibernate 无法满足我们的要求。这时 MyBatis 框架诞生了,它提供了更灵活、更方便的方法,弥补了 Hibernate 的这些缺陷。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论