一、第一个class和映射文件
package org.hibernate.tutorial.domain;
import java.util.Date;
public class Event {
private Long id;
private String title;
private Date date;
public Event() {}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
对一特定的 event, id
属性持有唯一的标识符(identifier)的值。如果我们希望使用 Hibernate 提供的所有特性,那么所有的持久化实体(persistent entity)类(这里也包括一些次要依赖类)都需要一个这样的标识符属性。而事实上,大多数应用程序(特别是 web 应用程序)都需要通过标识符来区别对象,所以你应该考虑使用标识符属性而不是把它当作一种限制。我们通常不会操作对象的标识(identity),因此它的 setter 方法的访问级别应该声明 private。这样当对象被保存的时候,只有 Hibernate 可以为它分配标识符值。你可看到Hibernate可以直接访问 public,private 和 protected 的访问方法和 field。所以选择哪种方式完全取决于你,你可以使你的选择与你的应用程序设计相吻合。
所有的持久化类(persistent classes)都要求有无参的构造器,因为 Hibernate 必须使用 Java 反射机制来为你创建对象。构造器(constructor)的访问级别可以是 private,然而当生成运行时代理(runtime proxy)的时候则要求使用至少是 package 级别的访问控制,这样在没有字节码指令(bytecode instrumentation)的情况下,从持久化类里获取数据会更有效率。
hibernate-mapping package"org.hibernate.tutorial.domain"
class name"Event" table"EVENTS"
id name"id" column"EVENT_ID"
generator class"native"
id
property name"date" type"timestamp" column"EVENT_DATE"
property name"title"
class
hibernate-mapping
在 hibernate-mapping
标签(tag)之间, 含有一个 class
元素。所有的持久化实体类(再次声明,或许接下来会有依赖类,就是那些次要的实体)都需要一个这样的映射。
id
元素是对 identifier 属性的声明。name="id"
映射属性声明了 JavaBean 属性的名称并告诉 Hibernate 使用 getId()
和 setId()
方法来访问这个属性。column 属性告诉 Hibernate EVENTS
表的哪个字段持有主键值。
嵌套的 generator
元素指定标识符的生成策略(也就是标识符值是怎么产生的)。在这个例子里,我们选择 native
,它提供了取决于数据库方言的可移植性。Hibernate 数据库生成的、全局性唯一的以及应用程序分配的标识符。标识符值的生成也是 Hibernate 的扩展功能之一,你可以插入自己的策略。(Native现在不被认为是最好的生成ID的策略)
注意:为什么 date
属性的映射含有 column
attribute,而 title
却没有?当没有设定 column
attribute 的时候,Hibernate 缺省地使用 JavaBean 的属性名作为字段名。对于 title
,这样工作得很好。然而,date
在多数的数据库里,是一个保留关键字,所以我们最好把它映射成一个不同的名字。
另一有趣的事情是 title
属性缺少一个 type
attribute。我们在映射文件里声明并使用的类型,却不是我们期望的那样,是 Java 数据类型,同时也不是 SQL 数据库的数据类型。这些类型就是所谓的 Hibernate 映射类型(mapping types),它们能把 Java 数据类型转换到 SQL 数据类型,反之亦然。再次重申,如果在映射文件中没有设置 type
属性的话,Hibernate 会自己试着去确定正确的转换类型和它的映射类型。在某些情况下这个自动检测机制(在 Java 类上使用反射机制)不会产生你所期待或需要的缺省值。date
属性就是个很好的例子,Hibernate 无法知道这个属性(java.util.Date
类型的)应该被映射成:SQL date
,或 timestamp
,还是 time
字段。在此例中,把这个属性映射成 timestamp
转换器,这样我们预留了日期和时间的全部信息。
注意:当处理映射文件时,Hibernate 用反射(reflection)来决定这个映射类型。这需要时间和资源,所以如果你注重启动性能,你应该考虑显性地定义所用的类型。