在hibernate中,有两种方式来暴露数据库标识:
持久化对象的identifier属性
通过Session.getIdentifier(Object o)的返回值
identifier属性很特殊,它的值是代表数据库行的主键。在我们的业务模型中,并不经常使用identifier属性,她仅仅是持久-关系相关,并不是业务问题。在我们的范例中,identifier属性经常被命名为id。因此如果 myCategory是Category的一个对象的话,通过调用myCategory.getId()就会返回代表了数据库中的主键。
你应该把访问identifier属性的访问方法设成public还是 private的呢?数据库标识符通常被应用程序用来处理特定的对象,即使在持久层之外也会同样有用。例如,web程序通常会展示给用户一个查询结果的摘要。当用户选择一个特定的元素的时候,应用程序需要取回被选择的对象。通常的做法就是寻找对象的标识符。因此通常把访问数据库标识的方法设为public更为妥当。
从另一方面说,我们经常把setId()方法设为private的,这样是为了让Hibernate自己生成和设置identifier的值。这里可能产生的一个问题,在持久化之前id就已经通过应用程序设置过了,而不是通过Hibernate生成的(我们会在下章讨论这个问题)。当identifier被初次分配以后,hibernate就不再允许应用程序再去修改它。
请记住,主键的定义的一部分就是它的值不允许被修改。我们来实现Category类的identifier属性:
public class Category{
private Long id;
…
public Long getId(){
return this.id;
}
private void setId(Long id){
this.id=id;
}
}
属性的类型依赖于CATEGORY表的主键类型以及Hibernate的映射类型。这个信息通过<id>属性来设置:
<class name=”Category” table=”CATEORY”>
<id name=”id” column=”CATEGORY_ID” type=”long”>
<generator class=”native”/>
</id>
…
</class>
identifer属性被映射到CATEGORY的CATEGORY_ID列。其Hibernate的类型为long。这个类型经常被映射到数据库的BIGINT类型上,它经常也被用来作为自动生成identifer的类型。因此,除了通过==和equals,你可以通过调用a.getId().equals(b.getId())来判断数据库的相等性。
另外一种处理数据库标识的方法并不是实现任何的identifer属性,而是让Hibernate内部管理数据库标识。在这个例子中,你可以忽略在映射声明中的name属性:
<id column=”CATEGORY_ID”>
<generator class=”native”/>
</id>
通过这样的设置,Hibernate就能自己内部管理identifer了。你可以如下方法来获取identifer的值:
Long catId=(Long)session.getIdentifer(category);
这个技术有个致命的缺点:你不能再使用Hibernate去有效的操作分散的对象。因此,你应该一直在Hibernate中使用identifer属性。
在Hibernate中使用数据库identifers非常直接和简单。而选择一个好的主键可能会更加困难些。我们将在接下来的部分讨论这些问题。