Hibernate命名策略及配置
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)
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
展示SQL脚本
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脚本,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脚本。用相结合的命名策略,你会获得双赢。
Hibernate命名策略及配置的更多相关文章
- 【spring boot hibernate】hibernate命名策略spring.jpa.hibernate.naming-strategy不起作用
对于 spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy hibernate命名策略设置之后 ...
- hibernate 命名策略
对于Java开发人员,Hibernate 3 annotations提供了非常好的方式来展示域分层.你可以很轻松的通过Hibernate自动生成需要的数据库架构,带有完整的SQL脚本.然而回到现实世界 ...
- Hibernate命名策略
hibernate的命名策略,可以减少对数据库标识符命名的维护,进一步减少这部份命名的重复性代码量,以提高维护. hibernate的命名方式,有两类,一类是显式命名,一类是隐式命名. 显式命名:在映 ...
- 攻城狮在路上(壹) Hibernate(三)--- 属性访问、命名策略、派生属性、指定包名等
一.hibernate访问持久化类属性的策略: 在<property>元素中的access属性用于指定Hibernate访问持久化类属性的方式. 常见的方式如下: 1.property:默 ...
- 【hibernate】hibernate不同版本的命名策略
===================================================hibernate 4命名策略如下================================ ...
- 80. Hibernate 5.0命名策略使用naming-strategy 不起作用【从零开始学Spring Boot】
[原创文章,转载请注明出处] 事情的起因:一不小心从1.3.3升级到了1.4.0版本,结果就碰到了各种悲催的事情了,好吧,Hibernate5.0的新特性就是其中一个坑,我们会发现我们配置的namin ...
- Hibernate入门之命名策略(naming strategy)详解
前言 JPA和Hibernate都提供了默认映射策略,通过映射将每个实体类映射到具有相同名称的数据库表,它的每个属性都映射到具有相同属性的列, 但是,在实际项目开发中可能出现与默认命名约定不匹配,也就 ...
- Hibernate之创建命名策略
在开发软件时,通常会要求每个开发人员遵守共同的命名策略.例如,数据库的表名及字段名的所有字符都要大写,表名以“S”结尾.对于Customer类,对应的数据库表名为CUSTOMERS.为了在映射文件中遵 ...
- 64.JPA命名策略【从零开始学Spring Boot】
[从零开始学习Spirng Boot-常见异常汇总] 在(39.2). Spring Boot Shiro权限管理[从零开始学Spring Boot] 这一章节中有人碰到这样一个问题"导入的 ...
随机推荐
- echarts 相关属性介绍
title: {//图表标题 x: 'left', //组件离容器左侧的距离,left的值可以是像20,这样的具体像素值, 可以是像 '20%' 这样相对于容器高宽的百分比,也可以是 'lef ...
- Codeforces Round #327 (Div. 2) C Median Smoothing(找规律)
分析: 三个01组合只有八种情况: 000 s001 s010 0011 s100 s101 1110 s111 s 可以看出只有010,101是不稳定的.其他都是稳定的,且连续地出现了1或0,标记为 ...
- Android(java)学习笔记100:使用Dexdump等工具进行反编译
使用Dex等工具进行反编译步骤: (1)首先找到Android软件安装包中的class.dex,把APK文件改名为".zip",然后解压缩其中的class.dex文件,这是Java ...
- BZOJ 4128: Matrix
BZOJ 4128: Matrix 标签(空格分隔): OI BZOJ 大步小步 矩阵 费马小定理 Time Limit: 10 Sec Memory Limit: 128 MB Descriptio ...
- 实现带复选框的TreeView控件
实现效果: 知识运用: TreeView控件的CheckView属性 //是否在树形视图控件中显示复选框 public bool CheckBoxs{ get;ser } 实现代码: TreeView ...
- 管理员必备的几个Linux系统监控工具
需要监控Linux服务器系统性能吗?尝试下面这些系统内置或附件的工具吧.大多数Linux发行版本都装备了大量的监控工具.这些工具提供了能用作取得相关信息和系统活动的量度指标.你能使用这些工具发现造成性 ...
- 通过Jquery获取RadioButtonList选中值
推荐 使用第二种,第一种有时候不起作用 第一种:通过find方法 获取RadioButtonList所选中的值 <script type="text/javascript"& ...
- Bootstrap历练实例:响应式标签页
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- 快速下载jar包
1, http://www.mvnrepository.com 2,可以从spring官网上下载,如果是mvn的话可以通过上面的网址下载
- 前端-带header和footer的双栏布局
目标是实现如上图带header和footer的双栏布局,其中右侧sidebar是固定宽度,左侧content是自适应: https://www.zybuluo.com/dengzhirong/note ...