Hibernate(至截稿时最新版本为4.1.3.Final)自动建表的表字段顺序总是随机的,之前我们总是自己写语句建好表,再使用Hibernate进行增删改查。始终是有点不方便。
最近看了下源码,发现很多地方都是使用LinkedHashMap或者是List来传输Entity里面的fields,觉得Hibernate应该是考虑到使用Entity里面定义的fields的顺序来实现建表语句里的表字段顺序的。
于是一步步跟踪下去,终于在一个地方发现了一个问题:org.hibernate.cfg.PropertyContainer在取fields的时候是使用TreeMap来保存的,于是试着改了下,将这个里面的所有TreeMap改成了LinkedHashMap,编译通过,打包,测试。
终于,我们期待已久的结果出来了:建表语句里面的字段顺序和Entity里面的fields的顺序一致了。
以下附上源码和修改后的代码:
源码:
private final
TreeMap<String, XProperty> fieldAccessMap;
private final
TreeMap<String, XProperty> propertyAccessMap;
private
TreeMap<String, XProperty> initProperties(AccessType access) {
if ( !( AccessType.PROPERTY.equals( access ) || AccessType.FIELD.equals( access ) ) ) {
throw new IllegalArgumentException( "Access type has to be AccessType.FIELD or AccessType.Property" );
}
// 其实通过以下注释也可以发现是Hibernate自己的一个失误
//order so that property are used in the same order when binding native query
TreeMap<String, XProperty> propertiesMap = new
TreeMap<String, XProperty>();
List<XProperty> properties = xClass.getDeclaredProperties( access.getType() );
for ( XProperty property : properties ) {
if ( mustBeSkipped( property ) ) {
continue;
}
propertiesMap.put( property.getName(), property );
}
return propertiesMap;
}
修改后的代码
private final
LinkedHashMap<String, XProperty> fieldAccessMap;
private final
LinkedHashMap<String, XProperty> propertyAccessMap;
private
LinkedHashMap<String, XProperty> initProperties(AccessType access) {
if ( !( AccessType.PROPERTY.equals( access ) || AccessType.FIELD.equals( access ) ) ) {
throw new IllegalArgumentException( "Access type has to be AccessType.FIELD or AccessType.Property" );
}
//order so that property are used in the same order when binding native query
LinkedHashMap<String, XProperty> propertiesMap = new
LinkedHashMap<String, XProperty>();
List<XProperty> properties = xClass.getDeclaredProperties( access.getType() );
for ( XProperty property : properties ) {
if ( mustBeSkipped( property ) ) {
continue;
}
propertiesMap.put( property.getName(), property );
}
return propertiesMap;
}
PS:通过以下代码可以测试建表时的语句:
public static void main(String[] args) {
Configuration cfg = new Configuration().configure();
SchemaExport export = new SchemaExport(cfg);
export.create(true, true);
}
建表语句会输出到控制台,对比之前未作修改时的语句,可以看出差别。
修改后数据库(MySQL 5.5.24)的对应表字段顺序和Entity定义的fields顺序一致。
我已将此改动向Hibernate开发组提出,希望以后会在官方版本里实现此改动。
链接如下:
https://forum.hibernate.org/viewtopic.php?f=1&t=1015920
分享到:
相关推荐
本资源包含的"hibernate总结练习源码"提供了对Hibernate ORM框架实际应用的实例,有助于深入理解和掌握其核心概念与功能。 1. **对象关系映射(ORM)**:Hibernate 提供了一种机制,将数据库中的表映射为Java类,表...
【标签】:“源码”和“工具”这两个标签表明我们将深入讨论Hibernate的内部实现原理,并且会涉及一些实际开发中使用的工具或技巧。 【内容】: 1. **配置文件(hibernate.cfg.xml)**:这是Hibernate的主配置文件...
**标题:“Hibernate Annotations”** **概述** Hibernate是一个流行的Java对象关系映射(ORM)框架,它简化了在Java应用程序中处理数据库的过程。Hibernate Annotations是Hibernate框架的一个重要组成部分,它...
在Java世界中,ORM(Object-Relational Mapping)框架如Hibernate是将数据库关系模型与对象模型之间进行映射的重要工具,极大地简化了数据库操作。本文将深入探讨Hibernate ORM中的一个关键概念:多对多双向中间实体...
2. **实体字段(Entity Fields)**:实体类中的成员变量,可以通过`@Id`、`@GeneratedValue`等注解定义主键和生成策略。 3. **实体关系(Entity Relationships)**:如一对一(OneToOne)、一对多(OneToMany)、多...
在传统的SQL世界里,ORM框架如Hibernate简化了与数据库的交互,而在NoSQL领域,Morphia扮演着相同的角色,使得开发者能够以面向对象的方式操作MongoDB数据,而无需直接编写低级的MongoDB查询语言。 **1. MongoDB和...
`entity jpa --class ~.domain.MyEntity --fields id:Long,name:String`会创建一个名为`MyEntity`的实体,带有`id`和`name`字段。这里的`~.domain`是实体所在的包名。 3. **数据访问对象(DAO)与服务层** Roo会...