【问题标题】:How to avoid hardcoded field names in HQL, Hibernate?如何避免 HQL、Hibernate 中的硬编码字段名称?
【发布时间】:2009-06-09 09:16:31
【问题描述】:

假设我有以下 HQL:

String hql = "select e.aField from MyEntity as e";

如果我想重构并将MyEntity 的成员变量aField 的名称更改为其他名称,我还必须更改字符串中整个代码中的所有匹配项。如果我忘记更改一个 hql 字符串,代码就会中断。

我怎样才能避免这种情况发生?

【问题讨论】:

    标签: hibernate refactoring hql hard-coding


    【解决方案1】:

    您可以使用NamedQueries - 您将 HQL 作为任何实体上的注释值,它们在启动时编译为 SQL。如果您在 hql 中有任何错误,您将无法启动您的 WebApp。

    【讨论】:

      【解决方案2】:

      使用足够聪明的 IDE,知道如何为您做这件事,比如 IntelliJ。如果我重命名一个类或变量,IntelliJ 会找到所有用途并为我管理更改。

      【讨论】:

        【解决方案3】:

        我相信您正在寻找我一直在寻找的东西......并找到了!

        我使用自定义 Hibernate 模板来生成我的 Java 代码。我只是拿了一份他们的副本,然后开始胡闹。听起来比实际更可怕 - 相信我。

        我在 PojoFields.ftl 文件中添加了以下代码:

        // These static property values are being generated by the POJO templates (PojoFields.ftl)
        <#foreach field in pojo.getAllPropertiesIterator()>
            <#if pojo.getMetaAttribAsBool(field, "gen-property", true)>    
               <#assign name = pojo.getPropertyName(field) type = pojo.getJavaTypeName(field, jdk5)>
            public static final String ${field.name}_propname = "${field.name}";    
               <#foreach column in field.getColumnIterator()>     
                  <#if pojo.getJavaTypeName(field, jdk5) == "String">
            public static final int ${field.name}_len = ${column.getLength()?c}; 
                     <#break>                 
                  </#if>    
              </#foreach>     
           </#if>   
        </#foreach>
        

        对于所有属性,它会生成一个具有属性名称的公共最终静态字符串。

        对于 String 属性,它会生成一个具有字段长度的 public final static int。

        public static final String  postalCode_propname         = "postalCode";
        public static final int     postalCode_len              = 15;
        

        只要我始终使用这些静态变量并且从不对它们的值进行硬编码,我将避免与数据库结构更改相关的运行时错误。

        例子:

        Criteria criteria = session.createCriteria(ClPost.class).add(
                    Restrictions.ne(ClPost.postalCode_propname, "90210"));
        
        String hql = "select e." + ClPost.postalCode_propname 
            + " from " + ClPost.class.getSimpleName() + " as e";
        

        【讨论】:

          【解决方案4】:

          你不能,因为它们只是字符串(根据定义很难重构)

          【讨论】:

            【解决方案5】:

            选项: 1. 使用 Criteria 而不是 HQL 2.使用NHibernateToLinq 3. 为每个类创建一个包含所有属性的枚举,并在 HQL 中使用它(需要串联)

            【讨论】:

            • 使用标准,您还需要将字段名称作为字符串。 Restrictions.eq("fieldname", foo) - 这与重构有同样的问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-10-29
            • 2018-11-19
            • 1970-01-01
            • 2022-10-31
            • 1970-01-01
            • 2020-05-28
            • 1970-01-01
            相关资源
            最近更新 更多