gist

2012年1月21日土曜日

「SQL文?何それおいしいの?」ORMLiteで楽しくAndroid開発しよう

Androidでは、SQLiteというデータベースが標準でサポートされています。

SQLiteを使うには、android.database.sqliteパッケージのSQLiteDatabase, SQLiteOpenHelper, SQLiteStatementあたりのクラスを使ってゴリゴリSQLを書くわけです。

SQLiteを使うコードの例

 public List<Account> getAllAccounts() {
                SQLiteDatabase database = dbHelper.getWritableDatabase();
  List<Account> accounts = new ArrayList<Account>();
  Cursor cursor = database.query("accounts",
    {"id","name","mail"}, null, null, null, null, null);
  cursor.moveToFirst();
  while (!cursor.isAfterLast()) {
   Account account = new Account();
   account.setId(cursor.getLong(0));
   account.setName(cursor.getString(1));
   account.setMail(cursor.getString(2));
   accounts.add(account);
   cursor.moveToNext();
  }
  cursor.close();
  return accounts;
 }

フィールド名の文字列やマッピングがコードに埋め込まれ、マジックナンバーになっています。これが問題になることがあります。

  • SQLの構文が正しいか実行するまでわからない。
  • SQLの構文が正しくても、スキーマとオブジェクトが意図通りマッピングされているか、実行するまでわからない。
  • SQL文でコードの見通しが悪くなる。
  • スキーマを共有するのが面倒。
  • ビジネスロジック以外のコードが増える。
  • スキーマ変更にメッチャ弱い。

他にもあると思います。

この問題を放置すると、気づかないうちに徐々に開発のペースを奪われます。リリース後では、機能追加や修正が困難な状態になっていることもあります。

ようするに「アプリの本質的なロジックだけに集中して開発できればいい」わけです。

ORMLiteは、これらの問題を解決するのに役立ちます。ORMLiteは、データベースの読み書きをするためのORM(Object Relational Mapper)です。


ORMLiteをダウンロードしてビルドパスを通す

必要なライブラリ


DatabaseHelperを作成する

DatabaseHelper.java

package com.luckyandhappy.models;

import java.sql.SQLException;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.util.Log;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {

 // SDCardのディレクトリを指定
 private static final String DATABASE_NAME = Environment.getExternalStorageDirectory() + "/Sample.db";
 private static final int DATABASE_VERSION = 1;

 public DatabaseHelper(Context context) {
  super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }

 @Override
 public void onCreate(SQLiteDatabase arg0, ConnectionSource arg1) {
  try {
   TableUtils.createTable(arg1, Account.class);
  } catch (SQLException e) {
   Log.e(DatabaseHelper.class.getName(), "データベースを作成できませんでした", e);
  }
 }

 @Override
 public void onUpgrade(SQLiteDatabase arg0, ConnectionSource arg1, int arg2,
   int arg3) {
  
 }
}


エンティティを作成する

Account.java

package com.luckyandhappy.models;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

@DatabaseTable(tableName = "accounts")
public class Account {

 @DatabaseField(generatedId = true)
 private Integer id;
 @DatabaseField
 private String name;
 @DatabaseField(canBeNull = true)
 private String mail;
 
 public Account() {}
 public Account(String name) { 
  this.name = name; 
 }
 public Account(String name, String mail) {
  this.name = name; this.mail = mail;
 }
 public Integer getId() { return this.id; }
 public String getName() { return this.name; }
 public void setName(String name) { this.name = name; }
 public String getMail() { return this.mail; }
 public void setMail(String mail) { this.mail = mail; }
}



モデルを作成する

AccountModel.java

package com.luckyandhappy.models;

import java.util.List;

import android.content.Context;
import android.util.Log;

import com.j256.ormlite.dao.Dao;

public class AccountModel {

 private static final String TAG = AccountModel.class.getSimpleName();
 private Context context;
 
 public AccountModel(Context context) {
  this.context = context;
 }
 
 public void save(Account account) {
  DatabaseHelper helper = new DatabaseHelper(context);
        try {
         Dao<Account, Integer> dao = helper.getDao(Account.class);
         dao.createOrUpdate(account);
  } catch (Exception e) {
   Log.e(TAG, "例外が発生しました", e);
  } finally {
   helper.close();
  }
 }
 
 public List<Account> findAll() {
  DatabaseHelper helper = new DatabaseHelper(context);
        try {
         Dao<Account, Integer> dao = helper.getDao(Account.class);
         return dao.queryForAll();
  } catch (Exception e) {
   Log.e(TAG, "例外が発生しました", e);
   return null;
  } finally {
   helper.close();
  }
 }
 
}


モデルを操作するアクティビティを作成する

ORMLiteExampleActivity.java

package com.luckyandhappy;

import com.luckyandhappy.models.Account;
import com.luckyandhappy.models.AccountModel;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class ORMLiteExampleActivity extends Activity {

 private static final String TAG = ORMLiteExampleActivity.class.getSimpleName();
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Account miku = new Account("初音ミク", "miku@vocaloid.net");
        Account rin = new Account("鏡音リン", "rin@vocaloid.net");
        Account len = new Account("鏡音レン", "len@vocaloid.net");
        Account ruka = new Account("巡音ルカ", "luka@vocaloid.net");
        
     AccountModel model = new AccountModel(this);
     model.save(miku);
     model.save(rin);
     model.save(len);
     model.save(ruka);
     
     for(Account account : model.findAll()) {
      Log.d(TAG, String.format("id=%s,name=%s,mail=%s",
        account.getId(),account.getName(),account.getMail()));
     }
     
    }
}

AndroidManifest.xmlを設定する

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.luckyandhappy"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ActiveAndroidExampleActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
</manifest>

実行結果

どんなデータベースができているでしょうか。SQLite Database Browserを使って確認してみます。

SQLiteのデータベースはひとつのファイルになっています。SDCard内のSample.dbを開きます。

accountsテーブルのスキーマです。

accountsテーブルのレコードです。きちんと登録されているのがわかります。

0 件のコメント: