`
Ryan_Wang
  • 浏览: 4883 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类

修改Hibernate源码实现建表时字段和Entity里定义的fields顺序一致

阅读更多
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
分享到:
评论
1 楼 Ryan_Wang 2017-01-12  
https://hibernate.atlassian.net/browse/HHH-11386

相关推荐

    hibernate总结练习源码

    本资源包含的"hibernate总结练习源码"提供了对Hibernate ORM框架实际应用的实例,有助于深入理解和掌握其核心概念与功能。 1. **对象关系映射(ORM)**:Hibernate 提供了一种机制,将数据库中的表映射为Java类,表...

    Hibernate element使用

    【标签】:“源码”和“工具”这两个标签表明我们将深入讨论Hibernate的内部实现原理,并且会涉及一些实际开发中使用的工具或技巧。 【内容】: 1. **配置文件(hibernate.cfg.xml)**:这是Hibernate的主配置文件...

    hibernate annotations

    **标题:“Hibernate Annotations”** **概述** Hibernate是一个流行的Java对象关系映射(ORM)框架,它简化了在Java应用程序中处理数据库的过程。Hibernate Annotations是Hibernate框架的一个重要组成部分,它...

    Hibernate ORM - 多对多双向中间实体关联关系

    在Java世界中,ORM(Object-Relational Mapping)框架如Hibernate是将数据库关系模型与对象模型之间进行映射的重要工具,极大地简化了数据库操作。本文将深入探讨Hibernate ORM中的一个关键概念:多对多双向中间实体...

    jpa

    2. **实体字段(Entity Fields)**:实体类中的成员变量,可以通过`@Id`、`@GeneratedValue`等注解定义主键和生成策略。 3. **实体关系(Entity Relationships)**:如一对一(OneToOne)、一对多(OneToMany)、多...

    Morphia一个nosql的ORM框架

    在传统的SQL世界里,ORM框架如Hibernate简化了与数据库的交互,而在NoSQL领域,Morphia扮演着相同的角色,使得开发者能够以面向对象的方式操作MongoDB数据,而无需直接编写低级的MongoDB查询语言。 **1. MongoDB和...

    Spring Roo命令文档

    `entity jpa --class ~.domain.MyEntity --fields id:Long,name:String`会创建一个名为`MyEntity`的实体,带有`id`和`name`字段。这里的`~.domain`是实体所在的包名。 3. **数据访问对象(DAO)与服务层** Roo会...

Global site tag (gtag.js) - Google Analytics