Java编程 - SQL语句应该存储在哪里?

Adr*_*ian 104 java sql

JDBC兼容的应用程序应该在哪里存储其SQL语句?为什么?

到目前为止,我设法确定了以下选项:

  • 在业务对象中硬编码
  • 嵌入在SQLJ子句中
  • 封装在单独的类中,例如 数据访问对象
  • 元数据驱动(将对象模式与数据模式分离 - 描述元数据中它们之间的映射)
  • 外部文件(例如属性或资源文件)
  • 存储过程

每个人的"优点"和"缺点"是什么?

SQL代码应该被视为"代码"还是"元数据"?

存储过程是否应仅用于性能优化,还是数据库结构的合法抽象?

性能是决定的关键因素吗?供应商锁定怎么样?

什么是更好的 - 松耦合或紧耦合,为什么?

编辑:谢谢大家的答案 - 这是一个总结:

元数据驱动即对象关系映射(ORM)

优点:

  • 非常抽象 - 无需更改模型即可切换数据库服务器
  • 广泛传播 - 实际上是一个标准
  • 减少所需的SQL数量
  • 可以将SQL存储在资源文件中
  • 表现(通常)是可以接受的
  • 元数据驱动的方法
  • (数据库)供应商独立性

缺点:

  • 隐藏SQL和真正的开发人员的意图
  • DBA很难对SQL进行审核/更改
  • 对于奇怪的情况,可能仍然需要SQL
  • 可以强制使用专有查询语言,例如HQL
  • 不适合优化(抽象)
  • 可能缺乏参照完整性
  • 替代缺乏SQL知识或缺乏对DB中代码的关注
  • 永远不会匹配本机数据库性能(即使它接近)
  • 模型代码与数据库模型非常紧密

硬编码/封装在DAO层中

优点:

  • SQL保存在访问数据的对象中(封装)
  • SQL很容易编写(开发速度)
  • 当需要更改时,SQL很容易跟踪
  • 简单的解决方案(没有凌乱的架构)

缺点:

  • DBA无法查看/更改SQL
  • SQL很可能成为特定于数据库的
  • SQL可能变得难以维护

存储过程

优点:

  • SQL保存在数据库中(靠近数据)
  • SQL由DBMS解析,编译和优化
  • DBA可以轻松地查看/更改SQL
  • 减少网络流量
  • 提高安全性

缺点:

  • SQL与数据库绑定(供应商锁定)
  • SQL代码更难维护

外部文件(例如属性或资源文件)

优点

  • 无需重建应用程序即可更改SQL
  • 将SQL逻辑与应用程序业务逻辑分离
  • 所有SQL语句的中央存储库 - 更易于维护
  • 更容易理解

缺点:

  • SQL代码可能变得无法维护
  • 更难检查SQL代码的(语法)错误

嵌入在SQLJ子句中

优点:

  • 更好的语法检查

缺点:

  • 与Java密切相关
  • 性能低于JDBC
  • 缺乏动态查询
  • 不那么受欢迎

Bal*_*usC 30

通常,应用程序在大小和/或可重用性方面增长得越多,就需要对SQL语句进行外部化/抽象化.

硬编码(作为静态最终常量)是第一步.下一步是存储在文件(properties/xml文件)中.元数据驱动(由像Hibernate/JPA这样的ORM完成)是最后一步.

硬编码的缺点是您的代码可能会特定于数据库,并且您需要在每次更改时重写/重新构建/重新分配.优点是你有一个地方.

存储在文件中的缺点是,当应用程序增长时,它可能变得不可维护.优点是您不需要重写/重建应用程序,除非您需要添加额外的DAO方法.

元数据驱动的缺点是您的模型代码与数据库模型非常紧密.对于数据库模型中的每个更改,您都需要重写/重新构建/重新分发代码.优点是它非常抽象,您可以轻松地从数据库服务器切换而无需更改模型(但现在问问自己:公司多久从数据库服务器切换一次?可能至少每3年一次,不是'是吗?).

我不会将存储过程称为"好"的解决方案.它们有着完全不同的目的.即使您的代码依赖于所使用的DB /配置.


fly*_*ire 21

我不知道这是否是最佳的,但根据我的经验,他们最终在DAO层中硬编码(即字符串文字).

  • 跟踪硬编码SQL所花费的所有时间都是工作安全性.如果您是唯一知道SQL所在位置的人,则不能被解雇. (21认同)
  • 令我感到惊讶的是,许多那些小心地构建精心设计的,干净的OO Java代码的人都是那些容忍编写凌乱,非高性能的SQL并且只是在随机位置将其作为字符串粘贴的人.如果您的SQL只是DAO层中的字符串,那么我几乎可以保证您的团队中没有DBA.至少不是*好*DBA. (11认同)
  • 它可能不是最佳的,但它也是我做的.易于编写,易于追踪,无需担心凌乱的架构. (5认同)
  • -1.拥有DAO是可以的,但至少可以将查询移动到某个属性文件中,以便DBA可以根据需要进行查看和调整! (3认同)
  • 我的经验是,如果您直接使用JDBC,如果您不能使用ORM解决方案,那么将查询字符串放在数据访问对象层中可能是最好的方法.有一点需要注意的是,如果你这样做的话,请确保每个人都在DAO类的编码标准的同一页面上.我一直在关注资源包和存储过程路由,因为它跨多个层展开数据访问逻辑,所以都是绝对维护的噩梦,因此在查询中添加一列需要您在不同的地方更改内容. (3认同)
  • 那么一个优秀的DBA会回答这个问题呢? (2认同)
  • 我不认为真正的 DBA 会为你进行代码审查。他不会检查每个查询,不会检查您的代码,也不会检查您的属性文件。他只会帮助你优化慢速查询。 (2认同)

Mic*_*mlk 12

我不认为有人会给你你想要的pro/con分解,因为这是一个相当大的问题.所以这就是我过去使用过的,以及我将要使用的内容.

我用来在DAL中使用SQL硬编码.我认为这很好,直到DBA想要使用SQL.然后你必须把它挖出来,格式化并将其解雇给DBA.谁会嘲笑它并取而代之.但是如果没有好的问号,或者问题标记的顺序错误,请将其粘贴在Java代码中.

我们也使用了ORM,虽然这对开发人员来说非常好,但我们的DBA讨厌它,因为没有SQL可供他们嘲笑.我们还使用了一个奇怪的ORM(来自第三方供应商的定制ORM),它习惯于杀死数据库.我从那时起就使用过JPA并且非常棒,但是通过DBA获得任何复杂的东西都是一场艰苦的战斗.

我们现在使用存储过程(调用语句硬编码).现在每个人都会抱怨的第一件事就是你与数据库联系在一起.你是.但是你多久更换一次数据库?我知道一个事实,我们甚至无法尝试它,依赖于它的其他代码的数量加上重新训练我们的DBA以及迁移数据.这将是一个非常昂贵的操作.但是,如果在您的世界中需要降低数据库,则可能需要SP.

展望未来我想使用存储过程和代码生成工具从Oracle包创建Java类.

编辑2013-01-31:几年后和DBA以后我们现在使用Hibernate,只在绝对需要时才进入SQL(在DB中存储过程).我认为这是最好的解决方案.99%的数据库不需要担心SQL,而他们这样做的1%是在他们已经熟悉的地方.

  • @Xepoch:我实际上同意 - 也许我应该以不同的方式措辞我的评论.您的数据库应该是您的数据模型(实体关系模型)的反映,您的对象模型也应该是您的数据模型的反映(尽管不一定相同).所以他们至少应该相关.在从存储过程生成Java代码方面,重点是用于访问数据库的API应该从数据模型的结构派生,而不是从对象结构派生的数据模型. (2认同)

Otá*_*cio 10

通过使用ORM(例如hibernate),您希望无需担心SQL语句.性能通常是可以接受的,您也可以获得供应商独立性.

  • -1您将拥有HQL语句,并且大多数问题仍然存在于HQL中.它们是否在代码内(字符串文字),注释中的命名查询,xml文件中的命名查询,存储在属性文件中? (13认同)
  • "使用Hibernate,使用HQL很少见"是迄今为止我听过的最有趣的事情.QBE很荒谬; 虽然你可能不得不**采用**标准来进行UI查询,但明确定义的查询(报告/服务交互等等)都应该在HQL中. (4认同)
  • @SingleShot - 我非常不同意.我们使用了大量的HQL,尤其是报告查询.标准根本不支持某些HQL功能(使用自定义SQL函数,select子句中的构造函数).QBE有时会导致更多问题然后解决. (3认同)
  • @SingleShot,我不同意.如果它比id选择更复杂,我认为**是用HQL完成的.我会说在使用用户界面驱动的搜索时使用标准和示例,就像在图书馆目录中的搜索屏幕中一样.但让我们看看其他人的想法. (2认同)

OMG*_*ies 10

SQL代码应该被视为"代码"还是"元数据"?

码.

存储过程是否应仅用于性能优化,还是数据库结构的合法抽象?

存储过程允许重用,包括在其他存储过程内部.这意味着您可以一次访问数据库并执行支持指令 - 最少的流量是理想的.ORM或者sproc,电线进入db&back的时间是你无法收回的.

由于它的抽象,ORM不适合优化.IME,ORM也意味着缺乏参考完整性 - 使数据库难以报告.现在已经增加了能够以可行的方式获取数据的复杂性.

性能是决定的关键因素吗?供应商锁定怎么样?

不,简单就是.供应商锁定也发生在数据库中 - SQL相对标准化,但仍有供应商特定的处理方式.

  • +1用于调用SQL代码.太多的ORM工具试图隐藏SQL,而事实上它通常是表达你想要做的事情的最佳语言.我同意你的意见,即存储过程比ORM更好,尽管我怀疑这将是一个流行的意见. (4认同)

小智 9

在java世界中对供应商锁定的恐惧是有趣的.

我希望您没有为Oracle Enterprise支付$ 50000 pr CPU,然后只使用最小公分母以便随时切换到Mysql.正如任何优秀的DBA都会告诉你的那样,不同的大名称数据库之间存在细微差别,特别是关于锁定模型以及它们如何实现一致性.

因此,不要仅基于供应商不可知SQL的原则来决定如何实现SQL调用 - 这样做有实际(商业)原因.


Joh*_*n K 6

存储过程中的SQL由数据库系统优化并为速度编译 - 这是它的自然之家.数据库系统理解SQL,由数据库系统解析.如果可以,请将SQL保留在数据库中; 将它包装在存储过程或函数或数据库系统提供的任何逻辑单元中,并使用您或任何其他人提到的任何工具对其进行简单调用.

为什么要在db之外存储数据库系统的SQL代码?通常是为了发展速度.为什么要使用ORM映射? - 有人说ORM映射提供了跨不同数据库系统的兼容性; 但是在现实世界中很少有应用程序在构建它时特别是当它开始使用复制等高级功能时从数据库平台转移,并且在极少数情况下确实会发生数据库系统被换出的情况,有些工作是有保证的.我相信ORM的一个缺点是它经常替代缺乏SQL知识或缺乏对db中代码的关注.即使它接近,ORM也永远不会匹配本机数据库性能.

我站在将SQL代码保存在数据库中并通过您希望使用的任何API或接口进行简单调用的方面.通过将这些调用放在抽象类或OO接口(由方法表示)后面,抽象出数据库调用的点,所以如果你换一种新的数据源,它将与业务层无缝连接. .


Ken*_*ack 5

你问的唯一一个有明确答案的问题是"是SQL代码还是元数据?" 这是最肯定的代码,因此应保持在某种源代码控制,有一个系统的更新很容易到最新版本,并回滚没有如果出了问题.

我已经看到了三种在应用程序中执行SQL的方法,每种方法都有它们的优点和缺点.没有最好的方法,但最好的方法是选择一个适合您的应用程序并坚持下去的方法.

  • ORM - 这减少了您需要编写的SQL数量并为您处理大量细节.您将需要执行一些自定义SQL.确保你有一个优雅地处理这个问题的ORM.
  • 数据访问对象 - 将SQL保留在访问数据的对象中.这封装了您的数据库并使其成为所以应用程序的其余部分不需要知道底层数据库结构,只需要了解这些对象的接口.
  • 存储过程 - 这可以将您的所有SQL保存在数据库中,使您的DBA可以轻松了解正在发生的事情.您需要做的就是让代码调用存储过程