2012-08-02 85 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類文件分離。