自己总结的Hibernate知识

本文分享了作者在达内学习Hibernate过程中的体会与总结,包括Hibernate的基本概念、五大接口、POJO、配置文件、映射文件等内容,并介绍了如何利用Ant工具简化开发流程。

    好久没来了,我已经在达内学习两个多月了,今天李翊老师让我们写博,以后也会常来的。

    我们的课程讲到web部分了,由于前面王海格老师讲解的JDBC、Hibernate的知识很深入,没能好好的消化,所以李翊老师帮我们串串线,带我们复习了两天的Hibernate。说实话,我的技术一直都不太好。以为原来看过点视频就觉得自己知识掌握的很多了,其实真的不是这样的。培训对于我这样的人来说真的很必要,因为我自己确实缺少程序员的某些正确的引导。

    扯远了,言归正传,总结一下我所学到的Hibernate知识,希望对自己或者看到本篇BLOG的人有用处吧,本人技术一般,还请多提意见。

 

-----------------以下内容我会尽量的少说废话,不过我相信,我写的东西,行里人都能看的懂---------------------------

    有很多人都说Hibernate不好用,慢。像李翊老师所说,其实你们还不会“玩”它。至于怎么个玩法,现在就逐一介绍。

 

    强烈声明,本文章不是初级教程,是对经验的总结。完全没有接触过Hibernate的朋友请绕道。

  

    Hibernate知识体系:1、五大接口(4接口、1类)

                                   2、POJO

                                   3、配置文件

                                   4、映射文件

                                   5、复杂映射

                                   6、优化(*)

1、五大接口

      ·Session接口:Session接口负责执行被持久化对象的CRUD操作(CRUD的任务是完成与数据库的交流,包含了很多常见的SQL语句。)。但需要注意的是Session对象是非线程安全的。同时,Hibernate的session不同于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而以后会将HttpSesion对象称为用户session。

  ·SessionFactory接口:SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

  ·Configuration接口:Configuration接口负责配置并启动Hibernate,创建SessionFactory对象。在Hibernate的启动的过程中,Configuration类的实例首先定位映射文档位置、读取配置,然后创建SessionFactory对象。

  ·Transaction接口:Transaction接口负责事务相关的操作。它是可选的,开发人员也可以设计编写自己的底层事务处理代码。

  ·Query和Criteria接口:Query和Criteria接口负责执行各种数据库查询。它可以使用HQL语言或SQL语句两种表达方式。

 

2、POJO

      简单Java对象。只有私有属性,getter、setter方法,有参构造方法和无参构造方法。有的还需要重写hashcode和equals方法。

 

3、配置文件

     是与数据库连接的相关参数。大概格式如下:

<?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.format_sql">true</property>
  <property name="hibernate.show_sql">true</property>

  <property name="connection.url">
   jdbc:mysql://localhost:3306/test
  </property>
  <property name="connection.username">root</property>
  <property name="connection.password">root</property>
  <property name="connection.driver_class">
   com.mysql.jdbc.Driver
  </property>
  <property name="dialect">
   org.hibernate.dialect.MySQLDialect
  </property>
  <mapping resource="org/whatisjava/domain/many2one.hbm.xml" />
  <mapping resource="org/whatisjava/domain/one2many.hbm.xml" />
  <mapping resource="org/whatisjava/domain/core.hbm.xml" />
 </session-factory>
</hibernate-configuration>

 

 

    其中,比较重要的属性是Hibernate.format_sql还有Hibernate.show_sql。前者是在执行测试类之后由IDE(我们用的MyEclipse)的控制台产生格式化好的SQL语句,后者是前者的保证,是在控制台显示SQL语句。我们知道Hibernate是对JDBC的封装,归根结底就是对数据库一系列操作,而操作数据库就要用到SQL语句,而Hibernate在后台做了什么,我们程序员当然需要去了解。因此我们才会关心这两个属性。其他属性,套用就可以了。

 

4、映射文件

    每个POJO都需要有一个映射文件。其实我们大多数时候就是操作映射文件,而感觉POJO只是个凑数的角色,没它不行,有它也很少去修改它,就这么个东西。而映射文件是格式化好的文本文件,我们用工具去生成一些诸如建表、查询的时候,一般都是Hibernate对映射文件的操作。映射文件的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.whatisjava.domain">
 <class name="Order" table="t_order">
  <id name="id" type="integer">
   <generator class="native"></generator>
  </id>
  <set name="items" cascade="all" inverse="true">
   <key column="order_id" foreign-key="fk_item_order" />
   <one-to-many class="Item" />
  </set>
  <property name="createDate" type="timestamp">
   <column name="create_date" />
  </property>
 </class>

 <class name="Item" table="t_item">
  <id name="id" type="integer">
   <generator class="native"></generator>
  </id>
  <many-to-one name="order" column="order_id" class="Order" />
  <property name="productName" type="string">
   <column name="product_name" not-null="true" length="50" />
  </property>
  <property name="price" type="big_decimal">
   <column name="unit_price" not-null="true" precision="7"
    scale="2" />
  </property>
  <property name="amount" type="integer">
   <column name="amount" />
  </property>
 </class>

 <query name="findAllOrder">
  <![CDATA[
  select distinct o from Order o left outer join fetch o.items
  ]]>
 </query>


</hibernate-mapping>

 

   很抱歉,传了个这么复杂的映射文件。用我们老师的话讲,是这东西,看懂你能看懂的就行,不用考虑它是干什么的。我也是一样的目的,就是介绍映射文件的作用而已。其中,除了一些常规的与POJO对应的属性外。我想介绍一些老师今天给我们讲的一些鲜为人知的使用经验。大家可以借鉴一下。

 

    在本映射文件中,大家有没有发现有些地方跟我们平常写的配置文件有些区别,好像是多了些什么参数,或者是格式有点不太一样是吧。没错,这些参数、格式,有的顾名思义,但是都是缺少官方或者详细的总结性的说法。因此我撰写本篇文章的目的就不言而喻了。(李老师说的好啊,Java这东西,照微软就是差在文档上,没一个像样的官方文档,愁~~~)

   

    首先,大家应该发现了,在这一个映射文件中好像是对应了两个class文件。没错,在我们实际的开发之中,自己写的映射文件实在没必要写成两个。因为别人也会写映射文件,因此,是自己写的映射文件,就大胆的放在一个映射文件之中吧。

    然后,看这里。

  <property name="price" type="big_decimal">
   <column name="unit_price" not-null="true" precision="7" scale="2" />
  </property>

    其实这里有两个小技巧。第一,我们平常好像把column是放在property中的吧,怎么拿出来单定义了呢?其实这里这样写是为了方便我们用一种叫Ant的工具。Ant老师也没给我们过多的介绍,只是知道它能够处理一些琐碎的事情。犹如一个秘书一样。我们用Ant只用到了,建立目录,通过映射文件在数据库中建立表,定义路径,通过映射文件建立POJO这些功能。我先列出代码吧。它就是一个名字为build.xml的文件。奇怪的是MyEclipse只要看到命名为build的xml文件就会在文件图标上有一只蚂蚁。

<?xml version="1.0" encoding="utf-8"?>
<project name="whatisjava.hibernate" default="clear" basedir=".">
 <path id="cp">
  <!--定义一组文件-->
  <fileset dir="lib">
   <include name="**/*.jar" />
  </fileset>
  <!--定义一个路径-->
  <pathelement path="bin" />
 </path>

 <!--定义一个扩展的Ant任务(hibernate)-->
 <taskdef name="hibernate" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="cp" />

 <target name="clear">
  <delete dir="bin" />
  <mkdir dir="bin" />
 </target>

 <target name="copy">
  <copy todir="bin">
   <fileset dir="src">
    <include name="**/*.xml" />
    <include name="**/*.properties" />
   </fileset>
  </copy>
 </target>

 <target name="schema" depends="clear,copy">
  <hibernate destdir=".">
   <classpath refid="cp" />
   <configuration configurationfile="bin/hibernate.cfg.xml" />
   <hbm2ddl drop="true" create="true" console="true" export="true" outputfilename="db.sql" delimiter=";" format="true" />
  </hibernate>
 </target>

 <target name="pojo" depends="clear,copy">
  <hibernate destdir="src">
   <classpath refid="cp" />
   <configuration configurationfile="bin/hibernate.cfg.xml" />
   <hbm2java jdk5="true" />
  </hibernate>
 </target>
</project>

大家能看懂吗?其实具体我也不知道为什么这样写,但是老师说了,只要你们会用就行了。所以,我也只是会用而已,并不了解它是为什么这样写的。我帮大家找了一些资料,大家看看比较官方的解释方法吧。

  1.<project>标签

  每个构建文件对应一个项目。<project>标签时构建文件的根标签。它可以有多个内在属性,就如代码中所示,其各个属性的含义分别如下。

  (1) default表示默认的运行目标,这个属性是必须的。

  (2) basedir表示项目的基准目录。

  (3) name表示项目名。

  (4) description表示项目的描述。

  每个构建文件都对应于一个项目,但是大型项目经常包含大量的子项目,每一个子项目都可以有自己的构建文件。

  2.<target>标签

  一个项目标签下可以有一个或多个target标签。一个target标签可以依赖其他的target标签。

  例如,有一个target用于编译程序,另一个target用于声称可执行文件。在生成可执行文件之前必须先编译该文件,因策可执行文件的target依赖于编译程序的target。Target的所有属性如下。

  (1).name表示标明,这个属性是必须的。

  (2).depends表示依赖的目标。

  (3)if表示仅当属性设置时才执行。

  (4)unless表示当属性没有设置时才执行。

  (5)description表示项目的描述。

  Ant的depends属性指定了target的执行顺序。Ant会依照depends属性中target出现顺序依次执行每个target。在执行之前,首先需要执行它所依赖的target。程序中的名为run的target的depends属性compile,而名为compile的target的depends属性是prepare,所以这几个target执行的顺序是prepare->compile->run。

  一个target只能被执行一次,即使有多个target依赖于它。如果没有if或unless属性,target总会被执行。

 

    先列出这两个吧,列多了大家迷糊。project标签姑且不说,他是Ant的标志。最重要的是target标签。其实一个Ant文件就是一大堆target的集合。一个target就是一个操作,比如编译文件,通过映射文件生成POJO或者通过映射文件生成数据库中表。大家还是要了target比较重要。

 

    先不说Ant了,大家有兴趣可以google。

 

    再说说我们的映射文件。

    

  <property name="price" type="big_decimal">
   <column name="unit_price" not-null="true" precision="7" scale="2" />
  </property>

 

还是上面的那句。我们把column放中间写就是为了方便Ant自动在数据库中产生表。unit_price字段相应的设置,非空,percision是标度,scale是小数点后面几位。格式就是XXXXX.XX这样。大概可以这样解释。

 

  在看这句

<query name="findAllOrder">
  <![CDATA[
  select distinct o from Order o left outer join fetch o.items
  ]]>
 </query>

 

   我们知道正常文本很少能出现<![CDATA[xxxx]]>这样奇怪的字符序列,所以设计者们用这个防止一些特殊符号如<,>,&等在XML文件中显示的问题。

   关键不是它,是query这个标签的作用。这个标签可以让我们不用在测试类中生成hql语句,而由映射文件来生成。这里还要注意hlq的select后面可以跟new出来的东西,只要是new的那个对象对应的类有相应的构造方法就可以。所及,请大家记住这个标签的作用。

 

   我拿出来的例子是many2one,one2many的例子。还有一个映射文件是十分重要的,具有很多有用的小功能,大家需要去掌握。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.whatisjava.domain">
 <class name="Message" table="t_message" dynamic-insert="true" dynamic-update="true">
  <id name="id" type="integer" column="id">
   <generator class="native" />
  </id>
  <property name="title" type="string">
   <column name="msg_title" length="50" />
  </property>
  <property name="content" type="string">
   <column name="msg_content" length="200" />
  </property>
  <property name="createDate" type="timestamp">
   <column name="create_date" />
  </property>
 </class>
</hibernate-mapping>

 

注意到没有,在class标签元素中,有这么两个属性, dynamic-insert="true" dynamic-update="true"。他们是干什么的呢。我们知道,Hibernate在MyEclipse控制台中生成SQL语句的时候总是那么的糟糕。我们经常使用JDBC的时候用preparedStatement来处理SQL,用了它之后我们可以使用预编译的SQL语句从而减少对数据库的操作。而这样有个弊端就是,如果我们需要插入或者查询10个字段中的两个字段的时候,总是显得力不从心,始终会出现10个问号(对应10个字段),如果字段多了,查询起来会大幅降低查询效率。因此我们用到这两个class标签属性来解决这个问题。其实这个属性对blob和clob类型数据更加的有效。

 

 

映射文件先告一段落吧。我们最关键的是优化,其实上面已经涉及很多优化的解决方案了。后面的只是补充而已。

 

5、复杂映射(穿插讲解吧) 6、优化

 

   关于sessionFactory.大家知道为什么它只定义一个吗?原因有三。一、它是个大对象。二、它要保证线程安全。三、要让它包装的对象是唯一个。而我们通常开发的时候,静态的变量由于只加载一次因此它是唯一的,就是这个道理。

 

   Hibernate中复杂映射使用频率排序(方便大家有针对性的学习Hibernate):

      many-to-one  >  one-to-many  >  many-to-many   >  one-to-one

 

 

 

(累了 ,明天过来继续更新)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值