`
guiqing85
  • 浏览: 162713 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

(转)扩展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

@Entitypublic 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),

       first_name varchar(255),

       last_name varchar(255),

       ...

       primary key (id)   

);

这样虽然很好,但是它不能解决你所的问题。还需要数据库命名约定。例如,每个表都可能从“T_”开始(比如T_CLIENT就是Client类),或者表中的每个字段可能以表中特定的前缀开始(比如写成CLI_FIRST_NAME和CLI_LAST_NAME)。为了能自动生成这些约束,你写自己的命名策略实施。自定义命名策略实现自定义命名策略最简单的方法是扩展ImprovedNamingStrategy类。这个类提供一些用户默认的情况,因此你只需实现你真正需要的方法就可以。你可以不去理睬通用样式任务的表名和列名方法,比如,把名称都加上大写字母。Hibernate生成表或列名时就会调用这种方法,甚至是在注释中明确指定的列名也会调用这种方法。,从ImprovedNamingStrategy类继承而来的addUnderscores()方法,可以派上用场,如示例7所示:

示例7:

public class MyNamingStrategy extends ImprovedNamingStrategy implements NamingStrategy {

    @Override

    public String columnName(String columnName) {

        return addUnderscores(columnName).toUpperCase();

    }

    @Override

    public String tableName(String tableName) {

        return addUnderscores(tableName).toUpperCase();

    }

}

接下来的示例8,展现的是如何在表名前加“T_”前缀,转换成名字前加大写字母和下划线。

示例8:

    @Override

    public String classToTableName(String className) {

        return "T_" + tableName(className);

    }

    @Override

    public String propertyToColumnName(String propertyName) {

        return addUnderscores(propertyName).toUpperCase();

    }

一个更复杂的命名策略命名策略接口实际上非常简单,但在很多方面受限制。首先,在任何特定的时间你无法知道调用方法的参数是属于哪个表。这样会受限制,比如,如果需要在表中每个列名前加表前缀,正如数据库约定所要求的。可以在classToTableName()方法中加变量成员存储当前的表,来解决这个限制。对于给定的表,这个方法将在propertyToColunmName()方法后被调用。例如,示例9为表创建了三个字母的前缀,加在表名及表中所有列名前。

示例9:

public class MyNamingStrategy extends ImprovedNamingStrategy implements NamingStrategy {

    private String currentTablePrefix;

    @Override

    public String classToTableName(String className) {

        currentTablePrefix = className.substring(0, 3).toUpperCase() + "_"$$

        return "T" + currentTablePrefix + tableName(className);

    }

    @Override

    public String propertyToColumnName(String propertyName) {

        return currentTablePrefix + addUnderscores(propertyName).toUpperCase();

    }

    @Override

    public String columnName(String columnName) {

        return addUnderscores(columnName).toUpperCase();

    }

    @Override

    public String tableName(String tableName) {

        return addUnderscores(tableName).toUpperCase();

    }

}

使用这种命名策略,Hibernate将产生如示例10的代码:

示例10:

create table TCLI_CLIENT (

        CLI_ID bigint generated by default as identity (start with 1),

        CLI_FIRST_NAME varchar(255),

        CLI_LAST_NAME varchar(255),

        ...

        primary key (CLI_ID)

);

外部关键字一般很难自动生成的外部关键字,构成了一个麻烦的问题。默认情况下,Hibernate可随机生成如“FKAB1273D65CCF7AB”这样的名字,DBA不会喜欢这样自动产生的命名。解决这个问题,需要使用@ForeignKey注释,如示例11所示:

示例11:

    @Entity

    public class Order {

        ...

       @JoinColumn(name = "CLIENT_ID")

       @ManyToOne(optional = false)

       @ForeignKey(name = "FK_CLIENT_ORDERS")

       private Client client;

       ...

    }

多对多关系当然,复杂的关系下(比如多对多的关系),上面所说的变得有些更复杂。例如,示例12中的SocialNerworker类,有许多朋友。这种情况下,你需要使用像@JoinTable,@ForeignKey这样的注释。

示例12:

    @Entity

    public class SocialNetworker {

        @ManyToMany

        @JoinTable(name = "TFRD_FRIEND",

                   joinColumns = {@JoinColumn(name = "NETWORKER_ID") },

                   inverseJoinColumns = {@JoinColumn(name = "FRIEND_ID") }

         )

        @ForeignKey(name = "FK_SNT_FRIENDS",

                     inverseName="FK_FRD_FRIENDS")

          }

        private Set<SocialNetworker> friends = new HashSet<SocialNetworker>();

        ...

    }

展示SQL脚本一旦你需要对数据库做改动或更新时,数据库管理员出于职责会很谨慎,可能会看要执行的SQL脚本,Hibernate可以通过SchemaExport工具,展示SQL脚本。你使用这个工具把要完成的模式生成普通的SQL脚本。当然,此类操作你不想做为构建过程的一部分去做,如果使用Maven,例如,你使用Hibernate3-maven-plugin自动生成数据库架构。关键部分如示例13所示,当然你可以设置drop和export为false,这样就相当于没有更新数据库资料。

示例13:

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>hbm2ddl</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <components>
                        <component>
                            <name>hbm2ddl</name>
                            <implementation>annotationconfiguration</implementation>
                        </component>
                        <component>
                            <name>hbmdoc</name>
                        </component>
                    </components>
                    <componentProperties>
                        <configurationfile>/target/classes/hibernate.cfg.xml</configurationfile>
                        <outputfilename>schema.ddl</outputfilename>
                        <namingstrategy>mycompany.myapp.IRDNamingStrategy</namingstrategy>
                        <drop>false</drop>
                        <create>true</create>
                        <export>false</export>
                        <format>true</format>
                    </componentProperties>
                </configuration>
            </plugin>

这样会生成SQL脚本,可以拿给DBA们看了。总结DBA命名惯例保留了下来,如果你将与他们共事,将需要顾及这些惯例。幸运的是,这并不意味着你要放弃Hibernate自动产生的数据库架构,也不用自已写SQL脚本。用相结合的命名策略,你会获得双赢。
原文地址:http://www.yeeyan.com/articles/view/38467/12438
分享到:
评论
1 楼 yzhw 2011-01-05  
从数据库生成实体时可能会遇到这样的问题,描述太长了,发个连接,里面有很详细的讲解
http://www.360doc.com/content/08/1231/15/94066_2235043.shtml

相关推荐

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     3.5 通过Hibernate API操纵数据库  3.5.1 Hibernate的初始化  3.5.2 访问Hibernate的Session接口  3.6 运行helloapp应用  3.6.1 创建运行本书范例的系统环境  3.6.2 创建helloapp应用的目录结构  3.6.3 把...

    Hibernate实战(第2版 中文高清版)

    第一部分 从Hibernate和EJB 3.0开始  第1章 理解对象/关系持久化   1.1 什么是持久化   1.1.1 关系数据库   1.1.2 理解SQL   1.1.3 在Java中使用SQL   1.1.4 面向对象应用程序中的持久化   1.2 范式不...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    本章主要介绍关系数据库中的代理主键(不具有业务含义),接着介绍Hibernate提供的几种内置标识符生成器的用法及适用范围。 6.1 关系数据库按主键区分不同的记录 123 6.1.1 把主键定义为自动增长标识符类型 123 ...

    ssh2(struts2+spring2.5+hibernate3.3)自动生成模版

    在网上search了这样的插件,以及相关的源码,对jsmart映象比较深,试用该插件后发现功能虽然强大(能够生成各种框架的环境搭建,以及fck等编辑器的初始化),但是发现有很多的规则受限制: 1.每次自动生成的代码都是一次...

    Hibernate+中文文档

    5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings...

    hibernate3.2中文文档(chm格式)

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    HibernateAPI中文版.chm

    HIBERNATE - 符合Java习惯的关系数据库持久化 Hibernate参考文档 3.2 -------------------------------------------------------------------------------- 目录 前言 1. 翻译说明 2. 版权声明 1. Hibernate...

    Hibernate 中文 html 帮助文档

    5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings ) ...

    Hibernate中文详细学习文档

    5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings...

    hibernate 体系结构与配置 参考文档(html)

    数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings ) ...

    精通Hibernate:对象持久化技术第二版part3

    本章主要介绍关系数据库中的代理主键(不具有业务含义),接着介绍Hibernate提供的几种内置标识符生成器的用法及适用范围。 6.1 关系数据库按主键区分不同的记录 123 6.1.1 把主键定义为自动增长标识符类型 123 ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     3.5 通过Hibernate API操纵数据库  3.5.1 Hibernate的初始化  3.5.2 访问Hibernate的Session接口  3.6 运行helloapp应用  3.6.1 创建运行本书范例的系统环境  3.6.2 创建helloapp应用的目录结构  3.6.3 把...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     3.5 通过Hibernate API操纵数据库  3.5.1 Hibernate的初始化  3.5.2 访问Hibernate的Session接口  3.6 运行helloapp应用  3.6.1 创建运行本书范例的系统环境  3.6.2 创建helloapp应用的目录结构  3.6.3 把...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     3.5 通过Hibernate API操纵数据库  3.5.1 Hibernate的初始化  3.5.2 访问Hibernate的Session接口  3.6 运行helloapp应用  3.6.1 创建运行本书范例的系统环境  3.6.2 创建helloapp应用的目录结构  3.6.3 把...

    Hibernate参考文档

    5.6. 数据库生成属性(Generated Properties) 5.7. 辅助数据库对象(Auxiliary Database Objects) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent collections) 6.2. 集合映射( Collection mappings ) ...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    本网站以xp为Web平台,JSP+Ajax+Servlet+JavaBean+Hibernate为网站实现技术,建立基于MySQL数据库系统的核心动态网页,实现博客网站前台及博客个人维护管理等功能模块。 1、 系统处理的准确性和及时性:系统处理的...

    服务器端接口编程.pptx

    本章服务器端接口编程主要介绍如何生成前台所需的数据,即如何获取请求,怎样与数据库交互,最后采取何种方式返回数据给前台。 服务器端接口编程全文共45页,当前为第3页。 本章导读 本章讲述服务器端接口编程相关...

    iBATIS实战

    11.1.1 Hibernate版本的DAO实现 194 11.1.2 JDBC版本的DAO实现 199 11.2 为其他数据源使用DAO模式 203 11.2.1 示例:为LDAP使用DAO 203 11.2.2 示例:为Web服务使用DAO 208 11.3 使用Spring DAO 209 11.3.1 编写代码...

Global site tag (gtag.js) - Google Analytics