精通Grails: Grails与遗留数据库
结合使用遗留 Java 类与 Hibernate 映射文件
了解了 mapping 块后,让我们再深入一步。不难想象如果拥有了遗留表,就有可能也拥有了遗留 Java 类。如果您想将现有 Java 代码与现有表中的数据融合,可以使用接下来的两个映射技术。
在 Java 1.5 引入注释之前,Hibernate 用户需要创建名为 HBM 文件的 XML 映射文件。回忆一下,GORM 是一个优于 Hibernate 的瘦 Groovy facade,因此,那些古老的 Hibernate 技巧仍然奏效也不足为奇。
首先,将遗留 Java 源文件复制到 src/java。如果使用包的话,要为每一个包名创建一个目录。例如,清单 9 中所示的 AirportHbm.java 文件位于 org.davisworld.trip 包中。这意味着该文件的完整路径应该是 src/java/org/davisworld/trip/AirportHbm.java。
清单 9. AirportHbm.java
public class AirportHbm {
private long id;
private String name;
private String iata;
private String state;
private String lat;
private String lng;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
// all of the other getters/setters go here
}
Java 文件一旦就位,就可以挨着它创建一个清单 10 中所示的名为 AirportHbmConstraints.groovy 的 “影子” 文件了。该文件中可以放置本应该位于域类中的静态 constraints 块。切记该文件一定要与 Java 类位于相同的包中。
清单 10. AirportHbmConstraints.groovy
static constraints = {
name()
iata(maxSize:3)
state(maxSize:2)
lat()
lng()
}
src 目录下的文件会在运行应用程序或者创建要部署的 WAR 文件时编译。如果已经编译了 Java 代码的话,也可以仅将它压缩为 JAR 文件并将其置于 lib 目录中。
接下来,让我们来建立控制器。按照约定优于配置的规定,控制器应该命名为 AirportHbmController.groovy。由于 Java 类位于一个包中,因此可以将控制器置于同一包中,或是在文件顶部导入 Java 类。我更偏爱导入的方法,如清单 11 所示:
清单 11. AirportHbmController.groovy
class AirportHbmController {
def scaffold = AirportHbm
}
接下来,将现有的 HBM 文件复制到 grails-app/conf/hibernate。应该会有一个如清单 12 所示的单一的 hibernate.cfg.xml 文件,您要在这里指定每一个类用的映射文件。在本例中,应该会有一个 AirportHbm.hbm.xml 文件的条目。
清单 12. hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping resource="AirportHbm.hbm.xml"/>
</session-factory>
</hibernate-configuration>
每一个类都必须有它自己的 HBM 文件。该文件为先前使用的静态 mapping 块的 XML 等价体。清单 13 展示了 AirportHbm.hbm.xml:
清单 13. AirportHbm.hbm.xml
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.davisworld.trip.AirportHbm" table="usgs_airports">
<id name="id" column="airport_id">
<generator class="native"/>
</id>
<property name="name" type="java.lang.String">
<column name="airport_name" not-null="true" />
</property>
<property name="iata" type="java.lang.String">
<column name="locid" not-null="true" />
</property>
<property name="state" />
<property name="lat" column="latitude" />
<property name="lng" column="longitude" />
</class>
</hibernate-mapping>
包的完整名是参考 Java 类而指定的。剩余的条目将 Java 名映射到表名。name 和 iata 字段条目演示了长表单。由于 state 字段在 Java 代码中和表中是一样的,因此可以将其条目缩短。最后两个字段 — lat 与 lng — 演示了缩短了的语法(想了解更多关于 Hibernate 映射文件的信息,参见 参考资料)。
如果 Grails 仍在运行的话,重新启动它。现在应该能够在 http://localhost:8080/trip/airportHbm 看到 Hibernate 映射数据。