二、Hibernate3.x功能演示
上面说了很多Hibernate的好处,也面就让我们来体会一下Hibernate3.x在这方面的卓越表现。我们将使用一个简单的Person-Employment-Oranization模型来说明。最简单的类是Person,下面是它的定义:
<class name="Person" lazy="true">
<id name="id" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<loader query-ref="person"/>
<sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
<sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
<sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
</class>
看了上面的定义,可能我们会首先注意到三个手写的SQL语句:INSERT、UPDATE和DELETE。其中的?将匹配上面所列的两个属性(这两个属性是id和name)。除了这个,这三条语句没有什么之处。
也许很多读者最感兴趣的是<loader>标签。这个标签定义了一个命名查询。这个查询在任何时候当我们使用get(),load()装载person或使用惰性关联获取数据时都会执行它。一般来讲,这个命名查询应该是一个SQL语句,如下面如示:
<sql-query name="person">
<return alias="p" class="Person" lock-mode="upgrade"/>
SELECT NAME AS {p.name}, ID AS {p.id} FROM PERSON WHERE ID=? FOR UPDATE
</sql-query>
注:一个本地的SQL查询可能会返回多个"实体列",但本例比较简单,只返回了一个实体。
Employment相对更复杂一点,而且并不是所有的属性都包括在INSERT和UPDATE中。定义如下:
<class name="Employment" lazy="true">
<id name="id" unsaved-value="0">
<generator class="increment"/>
</id>
<many-to-one name="employee" not-null="true" update="false"/>
<many-to-one name="employer" not-null="true" update="false"/>
<property name="startDate" not-null="true" update="false"
insert="false"/>
<property name="endDate" insert="false"/>
<property name="regionCode" update="false"/>
<loader query-ref="employment"/>
<sql-insert>
INSERT INTO EMPLOYMENT
(EMPLOYEE, EMPLOYER, STARTDATE, REGIONCODE, ID)
VALUES (?, ?, CURRENT_DATE, UPPER(?), ?)
</sql-insert>
<sql-update>UPDATE EMPLOYMENT SET ENDDATE=? WHERE ID=?</sql-update>
<sql-delete>DELETE FROM EMPLOYMENT WHERE ID=?</sql-delete>
</class>
下面是命名查询employment的定义:
<sql-query name="employment">
<return alias="emp" class="Employment"/>
SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
REGIONCODE as {emp.regionCode}, ID AS {emp.id}
FROM EMPLOYMENT
WHERE ID = ?
</sql-query>
下面的Organization的定义:
<class name="Organization" lazy="true">
<id name="id" unsaved-value="0">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<set name="employments"
lazy="true"
inverse="true">
<key column="employer"/>
<one-to-many class="Employment"/>
<loader query-ref="organizationEmployments"/>
</set>
<loader query-ref="organization"/>
<sql-insert>
INSERT INTO ORGANIZATION (NAME, ID) VALUES ( UPPER(?), ? )
</sql-insert>
<sql-update>UPDATE ORGANIZATION SET NAME=UPPER(?) WHERE ID=?</sql-update>
<sql-delete>DELETE FROM ORGANIZATION WHERE ID=?</sql-delete>
</class>
下面是两个命名查询的定义:
<sql-query name="organization">
<return alias="org" class="Organization"/>
SELECT NAME AS {org.name}, ID AS {org.id} FROM ORGANIZATION
WHERE ID=?
</sql-query>
<sql-query name="organizationEmployments">
<return alias="empcol" collection="Organization.employments"/>
<return alias="emp" class="Employment"/>
SELECT {empcol.*},
EMPLOYER AS {emp.employer}, EMPLOYEE AS {emp.employee},
STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
REGIONCODE as {emp.regionCode}, ID AS {emp.id}
FROM EMPLOYMENT empcol
WHERE EMPLOYER = :id AND DELETED_DATETIME IS NULL
</sql-query>
当我们看到这时,可能已经感觉到Hibernate的好处,那就是至少我们可以少维护数十行的Java代码。而且将这些代码转换成了XML配置文件,这样将使程序更加灵活和可维护。
下面的代码是我们的最后的工作,一个命名查询allOrganizationsWithEmployees的定义:
<sql-query name="allOrganizationsWithEmployees">
<return alias="org" class="Organization"/>
SELECT DISTINCT NAME AS {org.name}, ID AS {org.id}
FROM ORGANIZATION org
INNER JOIN EMPLOYMENT e ON e.EMPLOYER = org.ID
</sql-query>
虽然在现在为止还是有很多人喜欢直接使用SQL,这也包括我在内。但使用以Hbiernate为首的ORM框架可能会给我们带来更多的好处,如它自动产生的SQL一般会比我们手写的更优化。因此,Hibernate将成为软件大工业时代的新的操作数据库的标准。