日期:2014-05-16  浏览次数:20422 次

扩展hibernate生成数据库的命名规则

对于Java开发人员,Hibernate 3 annotations提供了非常好的方式来展示域分层。你可以很轻松的通过Hibernate自动生成需要的数据库架构,带有完整的SQL脚本。然而回到现实世界,你还需要考虑到,有时数据库管理员所使用的模糊的命名惯例。本文中,“Java Power Tools”的作者John Ferguson Smart将告诉你如何通过Hibernate自动生成数据库架构,而且还方便数据库管理。

Hibernate 3 注释有一种强大的持久管理数据库的方式,运用这些注释,你不需要为XML映射文件而费心,你可以设置成默认,由系统完成,从而减少了大量需要维护的代码。Hibernate提供了强大的自动生成数据库架构的工具,因此Hibernate可以自动完成生成和更新数据库架构的操作,你也无需担心那些不可思议的SQL脚本。

第一步:更新数据库架构

用Hibernate自动更新数据库架构很容易,你所需要做的只是设置好Hibernate.hbm2ddl.auto,如示例1:

示例1:

<hibernate-configuration>
   <session-factory>       
      <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
      <property name="hibernate.hbm2ddl.auto">create-drop</property>
      ...
      <!-- Persistent classes -->
      <mapping class="com.mycompany.myapp.domain.Client"/>
      <mapping class="com.mycompany.myapp.domain.Order"/>
      ...
   </session-factory>   
</hibernate-configuration>

设置它的属性为“create-drop”,那么每次启动应用程序都会产生新的数据库,这对集成测试很有用,但是有些情况下却不需要。另一方面,如果你设置这个值是为了更新,如果不存在数据库,Hibernate只会自动创建数据库,并更新与当前域模型匹配的所有表。

现在,在默认情况下,Hibernate将创建一套与Java类很相似的表及字段,从Java开发者的角度来看这样刚好符合要求。考虑下面的例子:

示例2:A simple persistent class

@Entity
public class Client implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
    ...
}
这个类中,Hibernate在默认情况下创建SQL模式,可以继续看示例3。
示例3:
create table Client (
        id bigint generated by default as identity (start with 1),
        firstName varchar(255),
        lastName varchar(255),
        ...
        primary key (id)
    );

旧的命名惯例

数据库的惯例约定有相当充分的理由存在,但是在任何情况下DBA常常要保守一些。开发者该如何做呢?

一个简单的解决办法是使用名字特征:@Entity、@Column注释,这种方法优于默认情况下,如示例4:

示例4:

@Entity(name="T_CLIENT")
public class Client implements Serializable {
    ...
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="CLIENT_ID")
    private Long id;

    @Column(name="FIRST_NAME")
    private String firstName;

    @Column(name="LAST_NAME")
    private String lastName;
    ...
}
这样很有作用,但是会有些麻烦,你不得不有更多的表。实际上,你必须对每个表及字段都做这样的操作。有没有更好的方法呢?
当然,你可以在Hibernate会话中定义命名策略集合取代默认值。这样的话你得写一个类,说明Hibernate如何定义表及字段名。
从ImprovedNamingStrategy类开始是一个恰当位置,用下划线转换类名,如SomeDomainEntity,转换成some_domain_entity。
在启动Hibernate会话时需准备这个类。如果你用Spring,需简化创建命名策略bean并为命名策略集合提供所创建的命名策略。
示例5就是Spring配置的典型说明:
示例5:
<bean id="sessionFactory" 
           class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
       <property name="dataSource" ref="dataSource" />
       <property name="configLocation" value="classpath:/hibernate.cfg.xml" />
       <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
       <property name="namingStrategy" ref="namingStrategy" />
    </bean>   

    <bean id="namingStrategy" class="org.hibernate.cfg.ImprovedNamingStrategy"/>
在这种命名策略下,Hibernate将生成如下面示例6的脚本:
示例6:
create table client (
        id bigint generated by default as identity (start with 1),