Java编程 – SQL语句应该存储在哪里?
JDBC兼容的应用程序应该在哪里存储它的SQL语句,为什么?
到目前为止,我设法确定了这些选项:
- 硬编码在业务对象
- embedded在SQLJ子句中
- 封装在单独的类中,例如数据访问对象
- 元数据驱动(将对象模式与数据模式分离 – 描述元数据之间的映射)
- 外部文件(例如属性或资源文件)
- 存储过程
每个人有什么“优点”和“缺点”?
SQL代码应该被视为“代码”还是“元数据”?
存储过程应该只用于性能优化还是数据库结构的合法抽象?
性能是决定的关键因素? 供应商locking呢?
有什么更好的 – 松耦合或紧耦合,为什么?
编辑:谢谢大家的答案 – 这里是一个总结:
元数据驱动即对象关系映射(ORM)
优点:
- 非常抽象的 – 数据库服务器可以切换而不需要改变模型
- 广泛传播 – 实际上是一个标准
- 切断所需的SQL数量
- 可以将SQL存储在资源文件中
- performance(通常)是可以接受的
- 元数据驱动的方法
- (数据库)厂商独立性
缺点:
- 隐藏SQL和真正的开发人员的意图
- SQL很难被DBA审查/更改
- SQL可能仍然需要奇数的情况
- 可以强制使用专有查询语言,如HQL
- 不适合优化(抽象)
- 缺乏参照完整性
- 替代缺乏SQL知识或在数据库中的代码缺乏谨慎
- 永远不要匹配本地数据库的性能(即使它接近)
- 模型代码与数据库模型紧密结合
硬编码/封装在DAO层
优点:
- SQL保存在访问数据的对象(封装)
- SQL很容易编写(开发速度)
- 当需要更改时,SQL很容易追踪到
- 简单的解决scheme(没有凌乱的架构)
缺点:
- SQL不能由DBA查看/更改
- SQL很可能成为DB特定的
- SQL可能变得难以维护
存储过程
优点:
- SQL保存在数据库中(接近数据)
- SQL由DBMSparsing,编译和优化
- SQL很容易让DBA查看/更改
- 减lessnetworkingstream量
- 增加安全性
缺点:
- SQL绑定到数据库(供应商locking)
- SQL代码很难维护
外部文件(例如属性或资源文件)
优点
- SQL可以在不需要重build应用程序的情况下进行更改
- 从应用程序业务逻辑中分离SQL逻辑
- 所有SQL语句的中央存储库 – 易于维护
- 更容易理解
缺点:
- SQL代码可能变得不可维护
- 更难以检查(语法)错误的SQL代码
embedded在SQLJ子句中
优点:
- 更好的语法检查
缺点:
- 与Java关系太密切
- 性能低于JDBC
- 缺乏dynamic查询
- 不是那么受欢迎
通常,应用程序在大小和/或可重用性方面的增长越多,需要对SQL语句进行外部化/放弃。
硬编码(作为静态最终常数)是第一步。 存储在文件(属性/ xml文件)是下一步。 元数据驱动(像Hibernate / JPA这样的ORM)是最后一步。
硬编码有一个缺点,就是你的代码很可能变成了数据库特有的,你需要在每次改变时重写/重新编译/重新分配。 好处是你有一个地方。
存储在文件中的缺点是,当应用程序增长时,它可能变得不可维护。 好处是你不需要重写/重build应用程序,除非你需要添加一个额外的DAO方法。
元数据驱动的缺点是您的模型代码与数据库模型紧密结合。 对于数据库模型中的每个更改,您都需要重写/重新编译/重新分发代码。 优势在于它非常抽象,您可以轻松地从数据库服务器切换而无需更改模型(但是现在问自己:公司从数据库服务器切换的频率是多less?每三年至less有一次可能,是吗?)。
我不会为存储过程调用这个“好”的解决scheme。 他们有一个完全不同的目的。 尽pipe如此,您的代码将依赖于所使用的数据库/configuration。
我不知道这是否是最佳的,但以我的经验,他们最终在DAO层硬编码(即string文字)。
通过使用一个ORM(如hibernate)你希望没有 SQL语句担心。 性能通常是可以接受的,而且您也可以获得独立供应商
我不认为有人会给你你想要的pro / con分解,因为这是一个相当大的问题。 所以相反,这是我过去所使用的,以及我将来会用到的。
我使用在DAL中使用硬编码的SQL。 我认为这是很好的,直到DBA想玩SQL。 然后你必须把它挖出来,格式化并将其发送给DBA。 谁会嘲笑它,取而代之。 但是如果没有好的问号,或者错误顺序的问号,就留在Java代码中。
我们也使用了一个ORM,虽然这对于开发人员来说是非常好的,但是我们的数据库pipe理员却讨厌它,因为没有SQL可供他们嘲笑。 我们还使用了一个奇怪的ORM(一个来自第三方供应商的定制的ORM),它有一个杀死数据库的习惯。 我从那以后就使用了JPA,并且非常棒,但是使用它过去DBA的任何事情都是一场艰难的战斗。
我们现在使用存储过程(使用硬编码调用语句)。 现在每个人都会抱怨的第一件事就是你被绑定到数据库。 你是。 但是,您多久更换一次数据库? 我知道一个事实,我们甚至无法尝试,其他代码的数量依赖于它,再加上再训练我们的数据库pipe理员和迁移数据。 这将是一个非常昂贵的操作。 但是,如果在你的世界里,变化的数据库在一滴帽子是必需的SP可能出。
outlook未来,我想使用存储过程和代码生成工具从Oracle包中创buildJava类。
编辑2013-01-31 :几年和DBA后来,我们现在使用Hibernate,只有在绝对需要的时候去SQL(在数据库中存储过程)。 我认为这是最好的解决scheme。 数据库不需要担心SQL的99%的时间,他们这样做的1%是在一个他们已经习惯的地方。
在Java世界中对供应商locking的恐惧是有趣的。
我希望您没有为Oracle Enterprise支付50000美元的CPU,然后只使用最小公分母来切换到Mysql。 正如任何一位优秀的DBA会告诉你的,不同的大名字数据库之间存在着细微的差别,特别是在locking模型和实现一致性方面。
所以,不要仅仅根据供应商不可知的SQL原则来决定如何实现你的SQL调用 – 有一个真实的(商业)原因。
SQL代码应该被视为“代码”还是“元数据”?
码。
存储过程应该只用于性能优化还是数据库结构的合法抽象?
存储过程允许重用,包括其他存储过程。 这意味着您可以一次访问数据库,并执行支持指令 – 最less的stream量是理想的。 ORM或存储过程中,电线上的时间去db和back是你不能recoup。
由于ORM的抽象,ORM不适合优化。 IME,ORM也意味着缺乏参考完整性 – 使数据库难以报告。 现在复杂性得到了保存,现在增加了能够以可行的方式获得数据。
性能是决定的关键因素? 供应商locking呢?
不,简单。 供应商locking同样也发生在数据库上–SQL是相对标准化的,但是仍然有供应商特定的做事方式。
存储过程中的SQL由数据库系统进行优化,并为速度进行编译 – 这是其自然之家。 SQL被数据库系统理解,由数据库系统parsing。 如果可以的话,把你的SQL保存在数据库中; 用存储过程或函数或数据库系统提供的任何逻辑单元包装它,并使用你或别人提到的任何一种工具对它进行简单的调用。
为什么要在数据库之外存储数据库系统的SQL代码? 往往是为了发展的速度。 为什么使用ORM映射? – 有人说ORM映射提供跨不同数据库系统的兼容性; 然而在现实世界中很less有应用程序在数据库平台build立之后,特别是在开始使用复制等高级function的时候迁移到数据库平台上,而且在极less数情况下会发生数据库系统被换出,有些工作是有保证的。 我相信ORM的缺点之一就是它经常替代缺乏SQL知识或者在db中缺乏谨慎的代码。 另外,ORM将永远不会匹配本地数据库性能,即使它接近。
我站在保持数据库中的SQL代码的一面,并通过您希望使用的任何API或接口进行简单的调用。 通过将这些调用放在抽象类或OO接口后面(用方法表示),也可以抽象出数据库调用的位置,所以如果您使用新types的数据源进行交换,它将与业务层。
你问的唯一的问题有一个明确的答案是“是SQL代码还是元数据? 这是最明确的代码,因此应该保存在某种源代码控制中,并且有一个系统可以轻松更新到最新版本,并在出现问题时不会回滚。
我已经看到了在应用程序中执行SQL的三种方法,每种方法都有其优点和缺点。 没有最好的办法,但最好的办法就是select一个适合你的应用程序,并坚持下去。
- ORM – 这减less了你需要编写的SQL的数量,并为你处理大量的细节。 你将需要做一些自定义的SQL。 确保你有一个ORM来处理这个优雅。
- 数据访问对象 – 将SQL保存在访问数据的对象中。 这封装了你的数据库,使得你的应用程序的其余部分不需要知道底层数据库结构,只是这些对象的接口。
- 存储过程 – 这将所有的SQL保存在数据库中,使DBA很容易知道发生了什么。 所有你需要做的是让你的代码调用存储过程
我们碰巧使用了iBatis SQL映射器,它比Hibernate等ORM更接近金属。 在iBatis中,您将SQL语句放入资源文件(XML)中,这些文件需要放在类path中。
如果您添加@ ocdecio的ORM选项,您的方法列表看起来相当全面。 我会说使用ORM和使用SQL映射器和资源文件是两个最好的方法。 我从SQLJ中明白了一点,它没有太多的吸引力,并且与Java过于紧密地联系在一起。 还要远离存储过程,因为它们将您与特定的数据库供应商联系起来(存储过程的标准几乎不存在)。
和我们大多数人一样,我已经看到了整个gammut,但我们需要考虑SQL一stream的语言。 我甚至看到存储在数据库中的SQL被下拉,然后执行备份。
我见过的最成功的系统使用存储过程,函数和视图。
存储过程将SQL文本保留在数据库中,并允许通过部署和定制(需要大量适当的devise来支持它)进行相对立即的更改。
所有的投影应该通过视图和简单的select出于同样的原因,所有的投影逻辑应该包含在视图内。
我build议使用工厂布局的DAO。 所以你需要的示例对象是:
public class CoolBusinessObject public class DAOFactory.java public implementation CoolBusinessOjectDAO public class CoolBusinessOjectDAOOracleImpl implements CoolBusinessOjectDAO
这种风格对数据交互进行分层,因此,如果切换数据库或转向使用ORM技术,则只需更改一层代码即可。
这三者之间并没有实质性的区别:
- 硬编码在业务对象
- embedded在SQLJ子句中
- 封装在单独的类中,例如数据访问对象
我假设你要将SQL代码直接embedded到Java代码中。 尽pipe1和3可能会直接使用JDBC(或者像Apache DbUtils这样的工具),但是2还是会在堆栈中添加一个预处理器技术,在编译之前生成相关的JDBC代码。
所以,从本质上讲,如果这些解决scheme涉及到embeddedSQL,那么您可以使用以下任何一种技术:
- JPA Criteria API ,将JPQLbuild模为Java中的内部域特定语言
- jOOQ ,将SQLbuild模为Java中的内部域特定语言
也许还有其他的工具可以帮助你以更安全的方式embeddedJava中的SQL,而不是通过SQLJ或通过实际的string连接。
从我曾经有过的经验来看,在DAO对象中硬编码sql语句是被广泛使用的,尽pipe如此,我认为它应该是最不可取的方法。 最好的做法应该是将sql语句存储在属性文件中。 通过一个接口来获取DAO对象中的语句,例如java.util.Properties 。 SQL语句可以散布为'?'来传递参数,通过Prepared Statement方法。
这种方法有助于将sql逻辑从应用程序业务逻辑中分离出来。 这使得所有的sql语句中央存储库成为可能,这使得修改变得更容易,而不需要在应用程序逻辑中search数据库语句。理解性也得到了改善。
我最终在资源捆绑。 我知道这是不正常的,但对我和任何“我以外的人”来说,这是最容易维护的。 这很简单,合乎逻辑。
我真的很好奇,看看有没有人使用我的方法。
作为rexem编写的SQL语句是代码 – 它们应该像代码一样对待,而不是外部化(但你有很好的理由),但放置了处理来自/去往语句的SQL数据的代码。 今天的框架ORMs / iBatis为日常的JDBC开发提供了很多简化。
一些你会在这个问题中发现你的问题的答案:)如何将你的SQL语句存储的问题取决于你的应用程序的王。 你有什么需求? 高安全性,易于编写代码或维护,跨平台或供应商locking? 接下来的问题是你需要纯SQL还是ORM框架会好?
* Hardcoded in business objects * Encapsulate in separate classes eg Data Access Objects
最简单的解决scheme(P),难以维护(C)
* Embedded in SQLJ clauses
Beter语法检查(P),缺lessdynamic查询(C),比JDBC(C)更低的性能,没有那么受欢迎(C)
* Metadata driven (decouple the object schema from the data schema - describe the mappings between them in metadata)
它必须是具体的情况下你应该这样做(C)或如果你的意思是ORM(P);)
* External files (eg Properties or Resource files)
(P),但很难检查错误(C)
* Stored Procedures
高安全性(P),难以维系供应商locking问题(C)