我不在我的源代码中包含使用硬编码的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()。
谢谢!
答案 0 :(得分:1)
我认为这不是一个好设计。你说你不是硬编码属性名称,但你是。
首先,您不必仅在您的实体中对属性名称进行一次硬编码,而是现在使用硬编码多次增加拼写错误的可能性,或者如果设计更改则另一个地方需要修复。
如果表或列发生变化,我不担心将来验证您的配置。您应该进行单元和集成测试(确实有测试吗?)来实际测试数据是否被正确读取并加载到模式中(在测试数据库中)。任何更改都是数据库架构是一个巨大的变化,肯定会对您的代码进行新的更新,因此它不太可能意外发生或没有通知。最后,如果您只是恰当地使用了hibernate属性映射,则只需在/如果列名称发生更改时更新单个位置。
最后,如果要更改对象中的方法名称,所有好的IDE都将具有重构支持,以自动更新使用该方法的所有位置。如果您只是传递String名称并使用Java Bean之类的名称来确定哪种方法,那将更难做到。