2012-08-02 41 views
2

当我创建JDBC应用程序,我通常做的是,硬编码“SQL语句”的Java程序。举例处理数据库:良好的软件工程概念

ResultSet rs = st.execute("select * from Users") 

但是,我听说这种方法并不是很好的软件工程概念。有人说所有这些sql语句都应该保留在数据库上作为“存储过程”,JDBC应该访问它们。从这两种方法可以归类为一个好的软件工程概念?请帮忙!

+2

你确定你确实是指“存储过程”吗?你可能会对“准备好的语句”感兴趣,这些语句阻止你进行SQL注入。 – cyroxx 2012-08-02 08:35:07

回答

4

你不会在这找到concensus,我预测。

存储的特效是用于封装复杂的数据库逻辑和查询,同时避免为了整理出数据传输的数据库/过滤/查询有用等

的缺点是,你常常会发现业务逻辑蔓延到存储程序,而它应该保留在应用程序本身中。

因此,在开发者/ dbas等之间经常存在一个关于这个逻辑应该驻留在哪里以及如何使用存储的特效的拔河。我会建议实事求是。本地化您的SQL查询,以便在更改SQL(表名等)时,不必在整个代码库中更改内容。利用存储过程来提高性能,当你在做代码复杂的东西时,但对数据库来说却微不足道。

+0

+1对于“你不会在这个问题上找到共识,我预测” – gresdiplitude 2012-08-02 08:49:26

+0

想象一下这样的事情:你需要得到(priceColumn * quantityColumn)* 2的答案。值“2”不会改变bcs它是算法。在这种情况下,什么是最好的? – 2012-08-02 09:09:12

+0

@Yohan - 我会*可能*在应用程序的业务逻辑中执行此操作,并将其移动到数据库,如果该表的大小和行数禁止有效xfer到应用程序。正如我所说,这里没有正确/错误的答案 – 2012-08-02 09:16:15

1

如果你硬代码,你可以在每次更改数据库中的一些时间来改变他们在源代码中的SQL语句。

通过使用存储过程,你只需要更改这些设置以及Java程序的源代码并不需要改变。

因此,我会推荐使用存储过程。

+1

如果没有参数更改,则不需要更改源代码。但是让我们说,如果你从JDBC向SP传递参数,那么在两处都需要改变 – 2012-08-02 08:31:06

+0

通过使用SP,你不需要知道java程序中数据库的结构(表名,列名,...) 。对这些的更改只需要对SP进行更改,而不是对java程序进行更改。 – Dahaka 2012-08-02 08:37:34

2

使用硬编码字符串和传递他们Statement肯定不是一个好的软件工程实践。

你应该总是使用PreparedStatement

例子:

String selectSQL = "SELECT USER_ID, USERNAME FROM DBUSER WHERE USER_ID = ?"; 
PreparedStatement preparedStatement = dbConnection.prepareStatement(selectSQL); 
preparedStatement.setInt(1, 1001); 
ResultSet rs = preparedStatement.executeQuery(selectSQL); 

存储过程也是很好的做法。大多数情况下,存储过程更多地用作性能透视图,因为除第一次运行外,您的查询是预编译的。

+0

你这么说,但是在OP的问题中,他在execute()语句中给出了一个非参数化的例子,这对我来说看起来很好 – 2012-08-02 08:50:26

+0

@BrianAgnew:是的,但是它是一个例子。我们可能不知道它的唯一类型的SQL查询OP将要执行。所以,我写信让OP知道 – 2012-08-02 08:54:19

2

这将是使用功能或存储过程中返回SYS_REFCURSOR数据库,并使用CallableStatement

如果您正在使用Oracle数据库从Java调用这些一个很好的做法,你可以尝试以下

数据库功能

CREATE OR REPLACE FUNCTION my_func (p_deptno IN number,p_emp_no IN varchar2) 
    RETURN SYS_REFCURSOR 
AS 
    p_cursor SYS_REFCURSOR; 
BEGIN 
    OPEN p_cursor FOR 
     select * 
     from emp 
     where deptno = p_deptno and emp_number=p_emp_no; 
    RETURN p_cursor; 
END; 
/

的Java

 callablestatement = 
       connection.prepareCall("begin ? :=my_func(?,?); end;"); 
callablestatement.registerOutParameter(1, OracleTypes.CURSOR); 
callablestatement.setString(2, param); 
callablestatement.setString(3, param); 
      callablestatement.execute(); 
      resultSet = ((OracleCallableStatement)callablestatement).getCursor(1); 

通过这种方法,你可以避免在Java中的SQL语句的硬编码。

+0

你这么说,但你的推理是什么? – 2012-08-02 08:49:26

+0

我想建议避免在java中硬编码的SQL语句的方法。通过这样做,它将如何成为与问题无关的东西?问问题的人应该说这与问题无关,而不是提出关于他人的建议和答案的意见。 – user75ponic 2012-08-02 09:47:56

+0

@Polappan:不难感受。我可以删除我的评论。这里没有什么是个人的 – 2012-08-02 10:39:49

2

使用休眠http://www.hibernate.org/(或另一个ORM),以便您不需要维护如此多的SQL语句。 Hibernate在后台为你生成大部分的SQL,这样你就不用担心维护SQL语句。

其他奥姆斯可太比如TopLink和OpenJPA的

2

我宁愿所有SQL查询存储为常量:

public static final String sqlEmpInsert = "SELECT EMP_NAME FROM EMPLOYEES"; 

在一个单独的Java类。我有单独的“常量”类文件为每个模块和一些模块,我将SQL查询存储在单独的属性文件中,以便它将从java类文件分离。