映射可以有两种形式:单独的XML文件或者POJO源代码中嵌入的Java 5注解。在本章中,我们要讨论注解的使用方法;在下一章中,将讨论XML文件的使用方法
Java 5在2004年末推出,成为Java语言的新版本。在此之前的Java版本不支持注解,所以尽管核心Hibernate3与以前的Java版本兼容,但是除非你的开发、编译和运行时工具至少支持Java 5(Java 6的代码是Mustang,已经于2006年发布了),否则无法使用本章中描述的特性。
因为假设你拥有Java 5环境,所以本章中的示例还将使用Java 5中引入的其他一些增强的语言特性,包括:
v 泛型(generic)。
v 增强的for循环
v 静态导入
v 枚举
v 自动装箱(autoboxing)
v 可变的参数列表
使用这些特性会使本章的源代码更加紧凑。同样,基于注解的映射也比等效的XML代码简洁得多。
使用注解就会将代码限制在Java 5环境中。这个限制会让一些开发人员根本无法使用注解,因为一些应用服务器还不支持这个版本的JVM。即使在使用最新的JVM方面不存在技术障碍,还有许多团队非常保守,不愿意贸然使用新的技术。
如果你已经有了支持代码的XML映射文件。如果没有明显的好处,你不会愿意用注解改写这些映射。
如果改写现有的POJO源代码,可能在原来没有问题的代码中引入bug。
如果在外部XML文件中维护映射信息,最大的好处在于可以直接修改映射信息来反映业务或数据库模式的变化,不需要重新编译整个应用程序。
与对XML映射文件的支持相比,Hibernate 3对基于注解的支持还不够成熟。
第一个优点(这可能是最大的优点)是,与XML映射相比,基于注解的映射要直观得多,因为它们直接放在源代码中,与相关联的属性放在一起。
注解比等效的XML映射要简洁得多。
Hibernate使用并支持EJB 3持久化注解。
在创建Hibernate应用程序时,如果对数据库有完全的控制能力,而且这是一个新项目,那么我们一般会建议使用注解。
如果你打算让应用程序能够移植到其他兼容EJB 3的ORM应用程序,那么必须使用注解重写映射信息。
如果要将现有的应用程序移植到Hibernate,或者要创建的新项目依赖于其他应用程序拥有的数据库,那么应该使用XML映射,XML映射的灵活性使你的项目不会受到数据库模式变化的严重影响。
需要安装Hibernate 3注解工具集(jar包),JDK5.0。
提示 如果希望在源代码中声明映射,但是无法使用Java 5环境,那么可以通过Xdoclet工具使用javadoc风格的注释实现相似的效果。从http://xdoclet.sourceforge.net可获得Xdoclet。
应用程序需要注解工具集中提供的hibernate-annotations.jar和ejb3-persistence.jar文件。
如果使用hibernate.cfg.xml文件建立映射配置,那么需要<mapping>元素提供被注解的类的完全限定名:
<mapping class=”com.hibernatebook.annotations.Book” />
在配置SessionFactory时,需要使用AnnotationConfiguration对象,而不是在使用XML映射时使用Configuration对象,如下所示:
AnnotationConfiguration config=new AnnotationConfiguration();
config.addAnnotatedClass(Book.class);
SessionFactory factory=config.configure().buildSessionFactory();
如果需要在EJB 3容器中使用加注解的实体,那么必须使用标准的EntityManager,而不是Hibernate特有的Session。Hibernate提供了一个可以单独下载的EntityManager实现。附录A中可以找到使用Hibernate EntityManager的详细说明。
在使用注解进行开发时,首先要编写一个Java类,然后在源代码中加上元数据注解。在J2SE 5.0中,JRE(Java Runtime Environment)会解析这些注解。Hibernate通过Java反射读取注解并且应用映射信息。如果希望使用Hibernate工具生成数据库模式,那么必须先编译包含注解的实体类。
表6-1列出了EJB 3 API中的所有持久化注解。在本节中,我们将结合一些简单的类来介绍比较重要的持久化注解,说明应用它们的方法。
表6-1 EJB 3注解
属性名 |
目 标 |
用 途 |
AttributeOverride/AttributeOverrides |
T、M和F |
覆盖嵌入的(组件)实体的默认列细节 |
Basic |
M和F |
覆盖基本字段和属性的默认读取策略和可空性 |
Column |
M和F |
将类的一个字段或属性与表中的一个列关联起来 |
ColumnResult |
Pm |
用作@SqlResultSetMapping注解的参数;允许在传统的JDBC ResultSet中以列的形式返回实体的字段 |
DiscriminatorColumn |
T |
在单一表或联结表继承策略中,覆盖识别符(discriminator)列的默认行为 |
DiscriminatorValue |
T |
在实体继承层次结构的根上,决定与识别符列中的实体相关联的值 |
Embeddable |
T |
表示一个实体是可嵌入的(组件)实体 |
Embedded |
M和F |
表示一个字段或属性由嵌入的(组件)实体组成 |
EmbeddedId |
M和F |
表示一个主键字段由嵌入的(组件)实体组成。这与@Id注解相互排斥 |
Entity |
T |
标识一个实体并允许覆盖属性(比如它的名称)的默认值 |
EntityListeners |
T |
在相关实体的生命周期中,允许调用适当的javax.persistence.EntityListener类 |
EntityResult |
Pm |
用作@SqlResultSetMapping注解的参数;允许在传统的JDBC ResultSet中以列的形式返回实体的字段 |
Enumerated |
M和F |
将一个字段或属性定义为enumerated类型 |
ExcludeDefaultListeners |
T |
在相关实体的生命周期中,不允许调用默认的EntityListener |
ExcludeSuperclassListeners |
T |
在相关实体的生命周期中,不允许调用超类的EntityListener |
FieldResult |
Pm |
用作@SqlResultSetMapping注解的参数;允许在传统的JDBC ResultSet中以列的形式返回实体的字段 |
GeneratedValue |
M和F |
允许为相关实体的主键值指定生成策略 |
Id |
M和F |
标识实体的主键。@Id属性的位置还决定实体类的默认访问模式是字段访问,还是属性访问 |
IdClass |
T |
表示一个实体的主键由与另一个实体的字段对应的列组成。组成主键的字段将标上@Id属性 |
Inheritance |
T |
表示一个实体是实体继承层次结构的根(也就是类继承层次结构中最高的持久类) |
JoinColumn/JoinColumns |
T、M和F |
表示列用作另一个表的外键 |
JoinTable |
M和F |
可以在一对多或多对多关系中指定链接表的细节 |
|