Java 避免硬编码休眠属性

Java 避免硬编码休眠属性,java,hibernate,Java,Hibernate,我不在源代码中包含使用硬编码的Hibernate属性名称,以避免在数据库或Hibernate配置发生更改时出现潜在的错误 我总是使用Hibernate标准和我创建的以下HibernateUtils.getPropertyName()方法来实现这一点 /** * Get a Hibernate property name.<p> * * <b>NOTE:</b> This method assumes all property names start with

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

我总是使用Hibernate标准和我创建的以下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;
}
/**
*获取Hibernate属性名。
*
*注意:此方法假定所有属性名称都以小写字符开头。
*
*@param方法检查器
*-忽略的值。此参数是调用感兴趣属性的“get”方法的占位符。
*@param methodName
*-用于检索感兴趣的属性的“get”方法的名称
*@返回属性名
*/
公共静态字符串getPropertyName(对象方法检查器,字符串方法名称)
{
字符串属性名称;
if(methodName.startsWith(“get”))
{
propertyName=methodName.substring(3,4).toLowerCase(Locale.ENGLISH)
+方法名称子串(4);
}
else if(methodName.startsWith(“is”))
{
propertyName=methodName.substring(2,3).toLowerCase(Locale.ENGLISH)
+方法名称子串(3);
}
其他的
{
抛出新的IllegalArgumentException(“方法名没有以'is'或'get'开头”);
}
返回propertyName;
}
为了使用它,我调用属性的“get”方法作为第一个参数,并硬编码第二个属性的“get”方法的名称

使用这种方法,Hibernate配置或数据库更改将导致编译时错误,而不是运行时错误

例如,如果供应商属性重命名为vendorname,则以下代码将导致运行时错误

Product Product=(Product)session.createCriteria(Product.class).add(Property.forName(“供应商”).eq(供应商)).uniqueResult()

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

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

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

如果供应商属性重命名为vendorname,则第二种方法将导致编译时错误,因为getVendor()方法将更改为getVendorname()

我想知道是否有另一种方法,可以让我完全消除HibernateUtils.getPropertyName()


谢谢

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

首先,不再只在实体中对属性名称进行一次硬编码,而是现在对其进行多次硬编码,从而增加了输入错误的可能性,或者在设计发生更改时需要在另一个地方进行修复

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


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

大多数人都会对Bean名称进行IDE重新计算,这样可以在不更改字符串的情况下很好地修复方法调用,而且无论如何您都不会看到编译时错误。。。。。这似乎是jUnit的工作,而不是为了防止将来的打字错误而对代码进行复杂化。dkatzel在下面提到了同样的问题。这是一个很好的观点。我之所以能够避免这种情况,是因为我强调在生成Hibernate类时使用这些类,而从不使用IDE进行重构。绝对值得一提。谢谢。从技术上讲,我不是硬编码财产名称。我故意对属性的get方法的名称进行硬编码。这是我让编译器告诉我在什么地方和什么时候自动中断的简单方法。你的错字点很好。为避免出现这种情况,请始终剪切并粘贴第二个参数。请详细说明您的陈述“如果您只是适当地使用hibernate属性映射”好吗?这可能就是我所缺少的。最后,关于最后一段,我的所有Hibernate类都是自动生成的,我从不更改它们的内容。