簡體   English   中英

如何有效重構Java中的SQLite訪問?

[英]How can I efficiently refactor SQLite access in Java?

我正在用Java編寫一個Android應用程序,該應用程序使用包含數十個表的SQLite數據庫。 我設置了一些數據源類,以從這些表中提取數據並將它們轉換為各自的對象。 我的問題是我不知道構造訪問Java中數據庫代碼的最有效方法。

數據源類變得非常重復,並且花費很長時間編寫。 我想將重復重構為一個父類,該父類將抽象出訪問數據庫和創建對象的大部分工作。

問題是,我是一個PHP(松散類型)程序員,而且我很難以嚴格類型化的方式解決此問題。

用PHP進行思考,我會做這樣的事情:

public abstract class Datasource {

    protected String table_name;
    protected String entity_class_name;

    public function get_all () {

        // pseudo code -- assume db is a connection to our database, please.
        Cursor cursor  =  db.query( "select * from {this.table_name}");

        class_name  =  this.entity_class_name;
        entity  =  new $class_name;

        // loops through data in columns and populates the corresponding fields on each entity -- also dynamic
        entity  =  this.populate_entity_with_db_hash( entity, cursor );

        return entity;
    }
}

public class ColonyDatasource extends Datasource {

    public function ColonyDataSource( ) {
        this.table_name  =  'colony';
        this.entity_class_name  =  'Colony';
    }
}

然后, new ColonyDatasource.get_all()將獲取表Colony中的所有行並返回一堆Colony對象,為每個表創建數據源就像創建一個只不過是將表信息映射到的類一樣容易。班級信息。

當然,這種方法的問題是我必須聲明我的返回類型,並且不能在Java中使用變量類名。 所以現在我被卡住了。

應該怎么做呢?

(我知道我可以使用第三方ORM,但是我的問題是,如果沒有一個ORM,有人將如何解決這個問題。)

如果您的查詢除了某些參數外幾乎相同,請考慮使用准備好的語句和綁定

在SQLite中,准備好的語句真的可以提高性能嗎?

首先,您不想在Java代碼中執行以下幾行:

class_name  =  this.entity_class_name;
entity  =  new $class_name;

可以按照您的建議進行操作,在Java之類的語言中,這稱為反射。 https://zh.wikipedia.org/wiki/Reflection_(計算機編程)

在這種情況下(很多情況下),使用反射進行所需的操作是一個壞主意,原因有很多。

列舉一些:

您的代碼應采用不同的結構以避免這種方法。

可悲的是,我確實相信,因為它是嚴格鍵入的,所以您無法自動執行代碼的這一部分:

// loops through data in columns and populates the corresponding fields on each entity -- also dynamic
        entity  =  this.populate_entity_with_db_hash( entity, cursor );

除非您通過反思的方式做到這一點。 或者完全轉移方法並開始序列化對象(不建議這樣做,只是說這是一個選擇!)。 或執行類似Gson https://code.google.com/p/google-gson/的操作 即將數據庫哈希值轉換為json表示形式,然后使用gson將其轉換為對象。

您可以做的是自動化抽象類中對象的“ get_all”部分,因為這幾乎對每個實例都是重復的,但是要使用實現,這樣您才能放心抽象函數可以調用它的方法擴展對象。 這將使您大部分采用“自動化”方法,從而減少了必須重新輸入的代碼量。

為此,我們必須考慮Java具有以下事實:

嘗試這樣的代碼(未經測試,極有可能不會編譯):

// Notice default scoping
interface DataSourceInterface {
    //This is to allow our GenericDataSource to call a method that isn't defined yet.
    Object cursorToMe(Cursor cursor);
}

//Notice how we implement here?, but no implemented function declarations!
public abstract class GenericDataSource implements DataSourceInterface {
    protected SQLiteDatabase database;

    // and here we see Generics and Objects being friends to do what we want.
    // This basically says ? (wildcard) will have a list of random things
    // But we do know that these random things will extend from an Object
    protected List<? extends Object> getAll(String table, String[] columns){
        List<Object> items = new ArrayList<Object>();

        Cursor cursor = database.query(table, columns, null, null, null, null,null);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            // And see how we can call "cursorToMe" without error!
            // depending on the extending class, cursorToMe will return 
            //   all sorts of different objects, but it will be an Object nonetheless!
            Object object = this.cursorToMe(cursor);
            items.add(object);
            cursor.moveToNext();
        }
        // Make sure to close the cursor
        cursor.close();
        return items;
    }
}

//Here we extend the abstract, which also has the implements.
// Therefore we must implement the function "cursorToMe"
public class ColonyDataSource extends GenericDataSource {
    protected String[] allColumns = {
        ColonyOpenHelper.COLONY_COLUMN_ID, 
        ColonyOpenHelper.COLONY_COLUMN_TITLE, 
        ColonyOpenHelper.COLONY_COLUMN_URL
    };

    // Notice our function overloading!
    //    This getAll is also changing the access modifier to allow more access
    public List<Colony> getAll(){
        //See how we are casting to the proper list type?
        // Since we know that our getAll from super will return a list of Colonies.
        return  (List<Colony>)super.getAll(ColonyOpenHelper.COLONY_TABLE_NAME, allColumns);
    }


    //Notice, here we actually implement our db hash to object
    // This is the part that would only be able to be done through reflection or what/not
    // So it is better to just have your DataSource object do what it knows how to do.
    public Colony cursorToMe(Cursor cursor) {
        Colony colony = new Colony();
        colony.setId(cursor.getLong(0));
        colony.setTitle(cursor.getString(1));
        colony.setUrl(cursor.getString(2));
        return colony;
    }
}

因此,我還沒有完全研究的另一種選擇是Java Persistence API,有些項目實現的注釋與此非常相似。 其中大多數以ORM的形式提供給您數據訪問對象( http://en.wikipedia.org/wiki/Data_access_object

一個名為“ Hibernate”的開源項目似乎是Java中ORM的首選解決方案之一,但我也聽說這是一個非常繁重的解決方案。 特別是當您開始考慮移動應用程序時。

特定於Android的ORM解決方案稱為OrmLite( http://ormlite.com/sqlite_java_android_orm.shtml ),這是基於Hibernate的,但經過了簡化,並且沒有太多依賴關系,因此無法將其放置在android上電話。

我已經讀過,使用一個的人會很好地過渡到另一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM