避免硬编码 Hibernate 属性

Posted

技术标签:

【中文标题】避免硬编码 Hibernate 属性【英文标题】:Avoid hard-coding Hibernate properties 【发布时间】:2014-01-06 19:51:26 【问题描述】:

我没有在我的源代码中包含使用硬编码的 Hibernate 属性名称,以避免在更改数据库或 Hibernate 配置时出现潜在的错误。

我总是使用 Hibernate Criteria 和我创建的以下 HibernateUtils.getPropertyName() 方法来完成此操作。

/**
* Get a Hibernate property name.<p>
*
* <b>NOTE:</b> This method assumes all property names start with a lower-case character.
*
* @param methodChecker
 *        - An ignored value. This parameter is a place-holder for a call to the "get" method for the property of interest.
 * @param methodName
 *        - The name of the "get" method used to retrieve the property of interest
 * @return The property name
 */
public static String getPropertyName(Object methodChecker, String methodName)

    String propertyName;
    if (methodName.startsWith("get"))
    
        propertyName = methodName.substring(3, 4).toLowerCase(Locale.ENGLISH)
                + methodName.substring(4);
    
    else if (methodName.startsWith("is"))
    
        propertyName = methodName.substring(2, 3).toLowerCase(Locale.ENGLISH)
                + methodName.substring(3);
    
    else
    
        throw new IllegalArgumentException("method name did not start with 'is' or 'get'");
    

    return propertyName;

为了使用它,我将属性的“get”方法调用为第一个参数,然后硬编码第二个属性的“get”方法的名称。

使用这种方法,Hibernate 配置或数据库更改将导致 COMPILE-TIME ERRORS 而不是 RUN-TIME ERRORS

例如,如果将 vendor 属性重命名为 vendorname,则以下代码将导致 RUN-TIME ERROR

产品 product = (Product) session.createCriteria(Product.class).add(Property.forName("vendor").eq(vendor)).uniqueResult();

要修复代码,所有出现的 vendor 都必须替换为 vendorname。显然,这很容易出错并且可能非常耗时。

我使用以下语句实现了相同的功能:

Product product = (Product) session.createCriteria(Product.class).add(Property.forName(HibernateUtils.getPropertyName(myProduct.getVendor(), "getVendor")).eq(vendor)).uniqueResult ();

如果将 vendor 属性重命名为 vendorname,第二种方法将导致 COMPILE-TIME ERRORS,因为 getVendor() 方法将更改为getVendorname()。

我想知道是否有其他方法 - 可以让我完全消除 HibernateUtils.getPropertyName()。

谢谢!

【问题讨论】:

大多数人会对 bean 名称进行 IDE 重构,这样会很高兴地在不更改字符串的情况下修复方法调用,并且无论如何您都不会看到编译时错误.....这看起来像jUnit 的工作,而不是复杂的代码以防止将来出现拼写错误。 dkatzel 在下面提到了同样的问题。这是一个很好的观点。我已经能够通过在生成 Hibernate 类时使用它们并且从不使用 IDE 重构来避免它。绝对是值得注意的事情。谢谢。 【参考方案1】:

我不认为这是一个好的设计。你说你没有硬编码属性名称,但你是。

首先,您不再只在实体中对属性名称进行一次硬编码,而是对它进行多次硬编码,从而增加了拼写错误的可能性,或者如果设计发生更改,则需要在另一个地方进行修复。

如果表或列发生更改,我不会担心将来对您的配置进行校对。您应该进行单元和集成测试(您确实有测试吗?)来实际测试数据是否被正确读取并加载到您的模式中(在测试数据库中)。任何更改都是数据库模式是一个巨大的更改,肯定会保证对您的代码进行新的更新,因此它不太可能意外或未经通知发生。最后,如果您只是适当地使用休眠属性映射,则只需在/如果列名称更改时更新单个位置。

最后,如果您想更改对象中的方法名称,所有优秀的 IDE 都将支持重构,以自动更新使用该方法的所有位置。如果您只是传递字符串名称并使用类似 Java Bean 的名称来确定它是什么方法,那将更难做到。

【讨论】:

从技术上讲,我不是硬编码属性名称。我故意硬编码属性的 get 方法的名称。这是我让编译器告诉我在哪里和什么时候自动损坏的简单方法。你的错字点很好。为了避免这种情况,总是剪切并粘贴第二个参数。您能否详细说明您的陈述“如果您只是适当地使用休眠属性映射”?这可能是我所缺少的。最后,关于你的最后一段,我所有的 Hibernate 类都是自动生成的,我从不更改它们的内容。

以上是关于避免硬编码 Hibernate 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何读取具有动态名称的文件,同时避免在 R 中进行硬编码?

如何避免硬编码?在装饰器中

MediaCodec 硬编码

如何避免在 COBOL 程序中硬编码凭据?

RStudio 和 SVN:如何提示连接细节以及如何避免硬编码?

改造 - 是不是可以避免从应用程序拦截器调用实际 api 并返回硬编码响应?