避免硬编码 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 属性的主要内容,如果未能解决你的问题,请参考以下文章