2013-05-13 75 views
0

我是新來的Java,我試圖實現一個基本的數據庫訪問層。 我正在使用Apache DBUtils來減少JDBC樣板代碼,這非常有效。如何減少數據庫訪問層中的代碼重複?

問題是我的實現對我的數據庫中的每個表使用一個單獨的CRUD類,並且感覺錯誤的是要複製這麼多的功能。

這是一個可接受的設計,如果不是我能做些什麼來減少代碼重複?
我可以重構我的解決方案以某種方式使用泛型嗎?

我意識到我可以使用一個ORM(myBatis,Hibernate等)作爲解決方案,但我想嘗試堅持使用DBUtils和普通的JDBC,如果我可以幫助它的話。

只是爲了澄清:
可以說我有2個表...

--------------------- 
User | File 
--------------------- 
userId | fileId 
name | path 
age  | size 
--------------------- 

在我目前的解決方案,我將創建2類(UserStore,FileStore的)和 每個類將實施類似的基本CRUD方法:

protected boolean Create(User newUser) 
{ 
    QueryRunner run = new QueryRunner(dataSource); 
    try 
    { 
     run.update("INSERT INTO User (name, age) " + 
       "VALUES (?, ?)", newUser.getName(), newUser.getAge()); 
    } 
    catch (SQLException ex) 
    { 
     Log.logException(ex); 
     return false; 
    } 
    return true; 
} 

protected User Read(int userId) 
{ 
    try 
    { 
     User user = run.query("SELECT * FROM User WHERE userId = ? ", userId); 
     return user; 
    } 
    catch (SQLException ex) 
    { 
     Log.logException(ex); 
     return null; 
    } 
} 

protected update(User user) 
{ 
    ... perform database query etc 
} 

protected delete(int userId) 
{ 
    ... perform database query etc 
} 
+0

模板方法不起作用,因爲...? – kutschkem 2013-05-13 09:00:43

+0

你的意思是Spring JDBC模板? – Fade 2013-05-13 09:05:50

+0

不,我的意思是模板方法模式http://en.wikipedia.org/wiki/Template_method_pattern – kutschkem 2013-05-13 09:10:43

回答

0

你問我如何用Template方法做到這一點。下面是一個例子,你可以做到這一點:

public class AbstractDAO<T> { 
private String table; 
private String id_field; 

public AbstractDAO(String table, String id_field){ 
this.table = table; 
... 
} 

public T read(int id){ 
    try 
{ 
    T user = run.query("SELECT * FROM "+ table + " WHERE "+id_field +" = ? ", id); 
    return user; 
} 
catch (SQLException ex) 
{ 
    Log.logException(ex); 
    return null; 
} 
} 

這一個看起來很容易,如何創建?

public boolean Create(T user){ 
    QueryRunner run = new QueryRunner(dataSource); 
try 
{ 
    run.update("INSERT INTO "+table+ getFields() + 
      "VALUES " + getParameters(user)); 
} 
catch (SQLException ex) 
{ 
    Log.logException(ex); 
    return false; 
} 

    return true; 
} 

protected abstract String getFields(); 
protected abstract String getParameters(T user); 

醜陋,不安全,但可以傳遞想法。

0

它看起來像我可以給你幾個簡單的建議,爲您的問題。

1)

而是管理查詢,就像你在做什麼,裏面的DAO中,讓有適合您的需求的查詢列表的工廠類。

class QueryFactory { 
    static String INSERT_BOOK = "BLAH"; 
    static String DELETE_BOOK = "BLAH"; 
} 

這將從DAO代碼單獨的查詢,並使其更易於管理。

2)

實現一個通用的DAO

http://www.codeproject.com/Articles/251166/The-Generic-DAO-pattern-in-Java-with-Spring-3-and

3)如你所提到的,使用ORM幫助自己結合豆類數據庫和更多的功能。

0

使用DBUtils,您已經提取了很多樣板代碼。剩下的主要是實體之間的不同之處:正確的sql語句,將實體對象轉換爲UPDATE參數,反之亦然,用SELECTs,異常處理。

不幸的是,創建一個對這些剩餘任務足夠靈活的通用抽象並不容易。這就是ORM映射器的全部內容。我仍然會建議看看其中的一個。如果你堅持使用JPA API,你仍然處於標準領域,並且能夠更容易地切換ORM提供者(雖然總是有一些耦合)。 SpringData的Repository抽象讓我印象深刻。在簡單用例他們給你代碼DAO的。如果你已經在使用Spring並且只想保持你的對象模型,你應該仔細研究它。

或者我用jooq做了一些很好的體驗。它還可以根據模式中的表創建DTO和相應的DAO。與ORM映射器相比,它更接近關係模式,這可能是一個優點或缺點。

0

MyBatis允許你返回一個與resultType作爲HashMap中:

<select id="mCount" resultType="hashmap"> select managerName, count(reportees) AS count from mgr_employee group by managerName; </select>

因此可以有效地編寫出這樣的工作流程: 1)開發接口 2A)使用MyBatis的註解來定義需要查詢或 2B)鏈路的接口的XML和編寫查詢

注意到,這不會有任何DAO等boilerplates涉及如上