2014年7月25日 星期五

java & Android SQLite database 基礎功能

這次因為老闆要用到手機APP能夠使用的資料庫(SQLite),所以我先使用java project進行資料庫的生成。
我:java project的寫完了,那我要轉交資料庫給阿睡處理了喔?
老闆:你能不能再寫個手機APP自動建立資料庫的版本?
我:.......

Java版本:


public class SQLiteHelper
{
public static String DataBase_NAME = "temp.db";
....
....
/for AndroidMatadata
private static String DataBase_TableName_AndroidMatadata = "android_metadata";
private static String DataBase_Col_Locale = "locale";
....
....
/*
* 因為java的專案本身不會附帶SQLite的lib,所以需要自己去jdbc提供處下載並引入java專案
* https://bitbucket.org/xerial/sqlite-jdbc
*/
public Connection getConnection() throws SQLException
    {
SQLiteConfig config = new SQLiteConfig();
// config.setReadOnly(true);
config.setSharedCache(true);
config.enableRecursiveTriggers(true);

SQLiteDataSource ds = new SQLiteDataSource(config);
ds.setUrl("jdbc:sqlite:" + this.DataBase_NAME);
return ds.getConnection();
//ds.setServerName("sample.db");
}
/*
* 給Anroid APP使用的資料庫,必須要先建立Matadata的"表格"與"內容",Android版本的會自動建立,Java需要手動建立
* 其中"DROP TABLE IF EXISTS " + TableName 的SQL指令,應該有碰過的都知道。這次是用來洗掉前一次舊的內容。
*/
public void PrapareTable_Android_Matadata(Connection con) throws SQLException
{
//建立表格
String sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_AndroidMatadata + "; "
        + "create table " + this.DataBase_TableName_AndroidMatadata + " ("
        + this.DataBase_Col_Locale + " TEXT"
        + ");";
                Statement stat = null;
                stat = con.createStatement();
                stat.executeUpdate(sql);
                //插入內容
                sql = "insert into " + this.DataBase_TableName_AndroidMatadata + " ("
        + this.DataBase_Col_Locale + ") values (?)";
                PreparedStatement pst = null;
                 pst = con.prepareStatement(sql);
                int idx = 1 ;
                pst.setString(idx++, "en_US");
                pst.executeUpdate();
}
/*
* 以下是新增單筆的內容
*/
public void insert_temptable(Connection con, DataRows inputdata) throws SQLException
       {
//插入內容
            String sql = "insert into " + this.DataBase_TableName + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routingId + ", "
        + this.DataBase_Col_SeqNo + ", "
        + this.DataBase_Col_GoingBack + ") values (?, ?, ?, ?)";
PreparedStatement pst = null;
                pst = con.prepareStatement(sql);
                int idx = 1 ;
                pst.setString(idx++, inputdata.Id);
                pst.setString(idx++, inputdata.routeId);
                pst.setString(idx++, inputdata.seqNo);
                pst.setString(idx++, inputdata.GoBack);
                pst.executeUpdate();
}
/*
     * 以下是新增多筆的內容,適合用於筆數較多的資料於新增操作。
     * 這裡需要注意的地方是 setAutoCommit(false) 的部分,因為要能夠快速塞入多筆內容,需要將資料庫的限制解除。
     * 一般情況大多都是一筆一筆的資料插入進資料表,這邊改成false的意思是讓commit變成非自動提交,
     * 如此一來,最後提交的時候就可以多筆資料一次性提交,而不會一筆一筆的進行提交。
     * setAutoCommit(false) → commit() or rollback();
     * 一般的使用到setAutoCommit()的情況,後面一定要進行commit() 或是 rollback()的防呆,以防資料庫提交的時候爆炸。
*
     * 使用setAutoCommit()的時候,一定要注意 PRIMARY KEY ASC AUTOINCREMENT 跟 UNIQUE的屬性與欄位對應。
     * 以防新增時出錯
     */
public void insert_BusStationLine(Connection con, ArrayList<BusStationInfo> inputdata) throws SQLException
    {
    String sql = "insert into " + this.DataBase_TableName + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routeId + ", "
        + this.DataBase_Col_SeqNo + ", "
        + this.DataBase_Col_GoBack + ") values (?, ?, ?, ?)";
        PreparedStatement pst = null;
        pst = con.prepareStatement(sql);
        con.setAutoCommit(false);
        for(int i = 0; i < inputdata.size(); i++)
        {
       int idx = 1 ;
       pst.setString(idx++, inputdata.get(i).Id);
       pst.setString(idx++, inputdata.get(i).routeId);
       pst.setString(idx++, inputdata.get(i).seqNo);
       pst.setString(idx++, inputdata.get(i).GoBack);
       pst.executeUpdate();
       pst.clearParameters();
        }
        con.setAutoCommit(true);
    }
}

Android版本:

public class DBHelper extends SQLiteOpenHelper
{
public static String DataBase_NAME = "StationInfo.db";
....
....
public String DatabasePath;
private Context mContext;
public SQLiteDatabase SQLite_DB;
public int DataBase_Version;
public String ProcessMsg;
/*
* 設定建構子
*/
public DBHelper(Context context, int version) 
{
super(context, DataBase_NAME, null, version);
mContext = context;
DataBase_Version = version;
DatabasePath = "/data/data/" + mContext.getPackageName() + "/databases/";
}
/*
* 外部開啟資料庫
*/
public boolean CheckDatabaseExist()
{
try{
SQLite_DB = SQLiteDatabase.openDatabase(DatabasePath + DataBase_NAME, null, SQLiteDatabase.OPEN_READONLY);
}catch(Exception e)
{
e.printStackTrace();
}
return SQLite_DB != null ? true: false;
}
/*
* SQLite的onCreate並不會隨著建構子的啟動而隨之開起。
* onCreate的執行主要是跟於getWritableDatabasec和getReadableDatabase之後執行。
* 執行條件:資料庫尚未建立!
* 假如資料庫已經建立的情況之下,即使執行了getWritableDatabasec和getReadableDatabase,也不會再次進入onCreate之中。
* 倒是可以外部或內部直接呼叫onCreate()強制執行。
*/
@Override
public void onCreate(SQLiteDatabase db) 
{
/*
* 創建三個表Busline、BusStation、BusStationLine
*/
SQLite_DB = db;
/*//for Android Matadata 因為Android會自己建立 所以這裡不用
String sql = "DROP TABLE IF EXISTS " + DataBase_TableName_AndroidMatadata + "; "
        +"create table " + DataBase_TableName_AndroidMatadata + " (" 
        + DataBase_Col_Locale + " TEXT"
        + ");";
db.execSQL(sql);*/
//for Table BusStationLine
sql = "CREATE TABLE " + DataBase_TableName + " (" 
+ DataBase_Col_Id + " VARCHAR,"
        + DataBase_Col_routeId + " VARCHAR,"
        + DataBase_Col_seqNo + " VARCHAR,"
        + DataBase_Col_GoBack + " VARCHAR"
        + ");";
db.execSQL(sql);
Log.e("OnCreate", "Table Create Finish!");
}
/*
* 單筆資料的新增
*/
public long insert_BusStationLine(BusStationInfo temp) 
{
SQLite_DB = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(DataBase_Col_Id, temp.Id);
cv.put(DataBase_Col_routeId, temp.routeId);
cv.put(DataBase_Col_seqNo, temp.seqNo);
cv.put(DataBase_Col_GoBack, temp.GoBack);
return SQLite_DB.insert(DataBase_TableName_BusStationLine, null, cv);
}
/*
* 以多載形式使用相同Func名稱來大量塞入資料。
* 同java專案的setAutoCommit(false)功能。
* 這裡是使用db.beginTransaction()、db.setTransactionSuccessful()、endTransaction();
* 將要處理的大量資料包於beginTransaction與setTransactionSuccessful之間即可。
*/
public void insert_BusStationLine(ArrayList<BusStationInfo> temp) 
{
SQLite_DB = getWritableDatabase();
String sql = "insert into " + this.DataBase_TableName_BusStationLine + " ("
        + this.DataBase_Col_Id + ", "
        + this.DataBase_Col_routeId + ", "
        + this.DataBase_Col_seqNo + ", "
        + this.DataBase_Col_GoBack + ") values (?, ?, ?, ?)";
SQLite_DB.beginTransaction();
SQLiteStatement stmt = SQLite_DB.compileStatement(sql);
for(int i = 0; i < temp.size(); i++)
{
       int idx = 1 ; 
       stmt.bindString(idx++, temp.get(i).Id);
       stmt.bindString(idx++, temp.get(i).routeId);
       stmt.bindString(idx++, temp.get(i).seqNo);
       stmt.bindString(idx++, temp.get(i).GoBack);
       stmt.execute();
       stmt.clearBindings();
       //Log.d("BusStationLine: ",Integer.toString(i+1));
       ProcessMsg = "BusStationLine: " + Integer.toString(i+1);
}
        SQLite_DB.setTransactionSuccessful();
        SQLite_DB.endTransaction();
}
/*
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
{
db = getWritableDatabase();
DataBase_Version = newVersion;
String sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusLine;
db.execSQL(sql);
sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusStation;
db.execSQL(sql);
sql = "DROP TABLE IF EXISTS " + this.DataBase_TableName_BusStationLine;
db.execSQL(sql);
//reset table
onCreate(db);
}
/*
* 以下是以前寫的code,其實內容很簡單,看看就好。
*/
public Cursor SearchNumberByKey(String Radical, String x)
{
//SQLiteDatabase dbc = this.getReadableDatabase();
//String[] columns = new String[]{FIELD_Number};
//String[] selectionArgs = {"%" + x + "%"};
//Number like ? 模糊搜尋、Number = ? 對照搜尋、(%'、'_' 符號便是 SQL 的萬用字元,前者代表任意長度字元,後者代表任意一個字元)
//return dbc.query(DataBase_TableName, columns, "Sum = "+ Radical +" and Number like ?", selectionArgs, null, null, null);
return null;
}
/*
* 以某欄位所指定的值來搜尋表的資料
*/
public Cursor SelectById(int position)
{
SQLite_DB = this.getReadableDatabase();
String Columns_ID = "_id";
return SQLite_DB.query(DataBase_TableName, null, Columns_ID + "=" +position, null, null, null, null);
}
/*
* 搜尋表的全部內容
*/
public Cursor SelectAll()
{
SQLite_DB = this.getReadableDatabase();
return SQLite_DB.query(DataBase_TableName, null, null, null, null, null, null);
//return db.query(TABLE_NAME, new String[] {"_id", "Space_set", "Sum", "Number", "word"}, null, null, null, null, null);
}
/*
* 更新
*/
public void UpdateHitPoint(int position, String HitPoint) 
{
SQLite_DB = this.getWritableDatabase();
String Columns_ID = "_id";
String Columns_HitPoint = "HitPoint";
ContentValues CV = new ContentValues();
CV.put(Columns_HitPoint, HitPoint);
SQLite_DB.update(DataBase_TableName, CV, Columns_ID + "=" +position, null);
}

沒有留言:

張貼留言