避免硬编码Hibernate属性

时间:2014-01-06 19:51:27

标签: java hibernate

我不在我的源代码中包含使用硬编码的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

产品产品=(产品)session.createCriteria(Product.class).add(Property.forName(“vendor”)。eq(vendor))。uniqueResult();

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

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

产品产品=(产品)session.createCriteria(Product.class).add(Property.forName(HibernateUtils.getPropertyName(myProduct.getVendor(),“getVendor”))。eq(vendor))。uniqueResult ();

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

我想知道是否可能有另一种方法 - 这使我能够完全消除HibernateUtils.getPropertyName()。

谢谢!

1 个答案:

答案 0 :(得分:1)

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

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

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

最后,如果要更改对象中的方法名称,所有好的IDE都将具有重构支持,以自动更新使用该方法的所有位置。如果您只是传递String名称并使用Java Bean之类的名称来确定哪种方法,那将更难做到。