当我创建 JDBC 应用程序时,我通常做的是将“sql 语句”硬编码到 java 程序中。举个例子
ResultSet rs = st.execute("select * from Users")
但是,我听说这种方法不是好的软件工程概念。有人说所有这些 sql 语句都应该作为“存储过程”保留在数据库中,而 JDBC 应该访问它们。从这两种方法来看,哪些可以归类为好的软件工程概念?请帮忙!
我预测,你不会对此达成共识。
存储过程可用于封装复杂的数据库逻辑和查询,同时避免将数据从数据库中传输出来以进行排序/过滤/查询等。
缺点是您经常发现业务逻辑潜入存储过程,而它可能应该保留在应用程序本身中。
因此,开发人员/数据库管理员等之间经常会就该逻辑应该驻留在哪里以及如何使用存储过程进行拉锯战。我建议务实。本地化您的 SQL 查询,这样当您更改 SQL(表名等)时,您不必更改整个代码库中的内容。使用存储过程来提高性能以及在执行代码复杂但对数据库而言微不足道的事情时。
使用硬编码的字符串并将它们传入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 );
存储过程也是很好的做法。大多数情况下,存储过程更多地用作性能角度,因为您的查询是预编译的,除了第一次运行。
在数据库中使用函数或存储过程将是一个很好的做法,这些函数或存储过程SYS_REFCURSOR
使用 java 返回并调用它们CallableStatement
如果您使用的是 Oracle 数据库,您可以尝试以下操作
数据库功能
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;
/
爪哇
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 语句进行硬编码。
使用 Hibernate http://www.hibernate.org/(或其他 ORM),这样就不需要维护这么多 SQL 语句。Hibernate 会在后台为您生成大部分 SQL,因此您无需担心维护 SQL 语句。
其他 ORM 也可用,例如 TopLink 和 OpenJPA
我更愿意将所有 SQL 查询存储为常量:
public static final String sqlEmpInsert = "SELECT EMP_NAME FROM EMPLOYEES";
在一个单独的 java 类中。我为每个模块设置了单独的“常量”类文件,对于某些模块,我将 SQL 查询存储在单独的属性文件中,以便将其与 java 类文件隔离开来。
如果您对 SQL 语句进行硬编码,则每次更改数据库中的某些内容时,您可能必须在源代码中更改它们。
通过使用存储过程,您只需要更改这些,并且您的 java 程序的源代码不需要更改。
因此,我建议使用存储过程。