Java 1.5:在数据库表的列名中保持常量的最佳实践是什么?

8

技术:

  • Java 1.5或1.6
  • Hibernate 3.4

为了避免在更改列名或表名时在多个位置更新列名,我想要一个常量文件。

我有以下问题?

  • 一个可能的解决方案是维护一个全局文件,其中存储了数据库中所有表列名的常量。 例如:

      class DbConstants
      {
              public static final String EMPLOYEE__PERFORMANCE_DESC="performance_desc";        
      } 
    
在上述情况中,employees是表的名称,performance_desc是列名的名称。 因此,为了避免两个不同表的两个常量发生冲突,遵循tablename__columnname格式来命名常量。
我看到这种方法的一个问题是,随着数据库增长,该文件中的常量数量将增加到数千个,这很难管理。另一个问题是如果表名更改,我必须更改所有表的前缀表名。
  • 假设我在上面的例子中更改列名从performance_desc到achievements_desc。在这种情况下,我很可能也想要更改常量,即从EMPLOYEE__PERFORMANCE_DESCEMPLOYEE__ACHIEVEMENT_DESC。由于在这种情况下我需要同时更改列名和常量名,因此我不认为在我的代码中使用常量而不是直接使用列名有多大用处,尽管有一个好处是在更改常量名时,我可以使用反射来反映常量名的更改,无论引用了哪个地方。 看起来要么没有太多使用常量的用处,要么我使用的方式不正确。

  • 在项目代码中,我看到人们为每个表列列表定义一个类来定义常量,如下所示。

      public class tbl_Employee
      {
              public static final PERFORMANCE_DESC=performance_desc;
      }    
    

这可以解决一些全局文件的问题,例如表名更改只会导致类名更改。

但是,这种方法的一个主要问题是我仅使用类来定义常量,这不是良好的编码实践。

  • 在某个地方读到过使用值字符串而不是整数的枚举类型,不确定它是否适用于Java 1.5或1.6,并且在给定情况下是否建议使用。

  • 对于定义数据库常量,最佳实践是什么?

  • 使用数据库常量真的有用吗?

  • 如果像上面提到的每个表使用一个类,我遇到的一个问题是命名约定。表名和相应类的名称之间的关系应该是什么,以定义表的列的常量。

  • 上述情况仅涵盖列名的情况,而不是表名。我可能希望在代码中使用常量而不是表名,那么为定义表名的常量应采取什么方法。

  • 通常认为,一旦发布产品或相关版本,表名和列名就不会经常更改。表名和列名的更改大多发生在开发阶段或功能增强(新版本)期间。这是避免使用表名或列名常量的有力论据吗?


与问题无关,您的示例违反了Java命名约定,使用了双下划线和类名如tbl_Employee。Java命名约定非常合理且被广泛使用。除非有充分的理由,否则不应该违反它们。 - Sergei Tachenov
@ Sergey Tachenov:完全同意,我只是为了举例而使用了错误的命名约定。但这引发了一个问题,我应该如何为定义表常量的类命名,因为正如您所说,表名约定不适用于类名约定。 - Maddy.Shik
不要这样做。如果你感觉需要解决这个问题,那么你正在错误地使用数据库。 - Ronnis
5个回答

9
听起来你正在问一些正确的问题 - 你想让代码更易维护,但意识到这可能会变得难以控制,并且可能会使代码变得更糟。可以考虑使用像“Color.RED, Color.BLACK”这样的东西。
我发现使用适量的常量可以使代码更易读。我认为类似于数据库列名之类的东西不应该包含在此类内容中,因为:
  • 它们不会经常更改,或者至少不应该经常更改

  • 有足够多的列名,你最终会得到一个大量的常量列表,此时人们停止使用它们,因为找到常量比在数据库中查找名称更困难。

我曾经看到过像这样的数据库文件,其中包含数千个常量,包括自定义查询、查询部分等等(甚至还有像public static final String COMMA=",";这样的宝石,以处理逗号拼写在未来可能会更改的可能性)。此时它们变成了“使用一次”的字符串,没有人敢改变它们。
关于字符串常量的另一个注意事项是,finals将编译为您的类作为字符串。因此,如果重新编译常量类,但不重新编译使用定义的类,则可能会导致新定义不传播。

1
我们不能否认一个事实,即在重命名列名时,在Java代码中复制相同的更改确实是一项繁琐且无生产力的任务。因此,我们不能放弃常量,我们必须有一些解决方案来避免数据库更改的乘数效应。正如我所指定的常量的一个好处,即使我们更改常量名称本身,在eclipse中也有重构功能。我的主要关注点是组织常量的最佳方法是什么,全局、类或接口或枚举每个表或其他一些东西。 - Maddy.Shik

2

您是否考虑过使用实体映射框架(如Hibernate)?

它可以将所有数据库表信息(以及所有其他特定于数据库的信息)存储在配置文件中。它还提供了一个分离层,用于“硬”数据库设计和应用程序之间(这将使吸收任一方面的更改更加容易)。


我正在使用Hibernate注解将实体类映射到表。但是有些数据库查询无法通过Hibernate解决,因此在Dao层中使用SQL查询来实现相同的功能。 - Maddy.Shik
您也可以将标准的SQL查询嵌入到Hibernate配置文件中。这意味着对数据库的任何更改都需要相应地更改配置文件,但这确实允许您仅影响一个位置的数据库更改(而不需要重新编译即可生效)。请查看Hibernate文档中的本地SQL查询部分。 - Jonathan B
(1). 我正在使用Hibernate注解而不是Hibernate映射文件。因此更改将在多个文件中进行。 (2). 有一些业务查询无法通过Hibernate POJO回答,因此我必须在DAO层的上下文之外编写代码。谢谢。 - Maddy.Shik
如果您在查询中没有指定特定的POJO对象映射,Hibernate也会为您提供原始数据。因此,您可以编写具有select语句的HQL,返回的迭代器(或列表)是一个包含从查询返回的数据的Object[]列表。 - Jonathan B
1
注释是易于阅读的代码和更难维护代码之间的权衡。这不是一个容易做出的决定 - 做最适合您的选择。 - Jonathan B

1

看起来不错,但我认为无论是接口还是类,仅将它们用于定义常量并不被认为是好的做法。但是,这个链接反映了正在遵循的实践,因此可能会有用。但是,需要针对表名的常量,而这段代码没有涉及到。 - Maddy.Shik
@Don 链接已失效 - nanosoft

1
在我的当前项目中,我们大量使用注释来处理许多与数据库相关的元数据,因为我们无法使用像Hibernate这样的框架。对于实际的列常量,是的,我们使用了经过验证的public static final String。是的,它相当脆弱。

Daniel DiPaolo:你是使用一个全局文件还是每个表使用一个类? - Maddy.Shik
每个表对应一个类,虽然它并不严格绑定于表名,但表名也是类中的常量 :) - Daniel DiPaolo

0
当我拥有关于数据库的元数据时,我也会将其存储在数据库中。这是我看到其他系统运行的方式,如果不是最初,那么最终都会这样。为了确保这些数据得以维护,你可以根据数据库架构进行检查。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接