Android의 Sqlite 기본 사용 및 흐림 제거

52099 단어
qlite는 우리가 일상적인 업무에서 자주 사용하는 데이터 저장 방식으로 장기적으로 저장해야 하거나 대량의 데이터를 저장하는 데 적합하다. 오늘 우리는 기본적인 사용을 소개한다.
1. 기본 사용
먼저 SQLiteOpenHelper 클래스를 계승해야 합니다. SQLiteOpenHelper 클래스에 대한 설명을 볼 수 있습니다.
/**
 * A helper class to manage database creation and version management.

데이터베이스 생성과 버전 제어를 담당하는 클래스입니다.계승 후 구조 함수를 다시 써야 하며 구조 함수는 네 개의 매개 변수로 구성된다.
	public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
            @Nullable CursorFactory factory, int version) {
        this(context, name, factory, version, null);
    }

이름은 데이터베이스 이름이고factory는CursorFactory 유형입니다. 원본 코드를 보면CursorFactory가 인터페이스라는 것을 알 수 있습니다. 코드는 다음과 같습니다.
	/**
     * Used to allow returning sub-classes of {@link Cursor} when calling query.
     */
    public interface CursorFactory {
        /**
         * See {@link SQLiteCursor#SQLiteCursor(SQLiteCursorDriver, String, SQLiteQuery)}.
         */
        public Cursor newCursor(SQLiteDatabase db,
                SQLiteCursorDriver masterQuery, String editTable,
                SQLiteQuery query);
    }

주석에서 알 수 있듯이 이 방법은 우리가 데이터베이스에서 조회 작업을 수행할 때query의cursor 대상을 되돌려주는 것이다. 우리는 SQLiteDirectCursorDriver 종류의query 방법에서 이 인터페이스의 사용을 볼 수 있다.
	public Cursor query(CursorFactory factory, String[] selectionArgs) {
        final SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, mCancellationSignal);
        final Cursor cursor;
        try {
            query.bindAllArgsAsStrings(selectionArgs);

            if (factory == null) {
                cursor = new SQLiteCursor(this, mEditTable, query);
            } else {
                cursor = factory.newCursor(mDatabase, this, mEditTable, query);
            }
        } catch (RuntimeException ex) {
            query.close();
            throw ex;
        }

        mQuery = query;
        return cursor;
    }

여기에 우리는 이 파라미터를 필요로 하지 않기 때문에 비우면 된다. 버젼은 데이터베이스 버전이고 1로 전송하면 된다. 후속 데이터베이스 업그레이드가 필요하면 버전 제어를 잘 해야 한다.그 다음에 onCreate와 onUpgrade를 다시 쓰는 방법은 데이터베이스를 만들고 데이터베이스를 업그레이드하는 것이다. 저는 시스템 응용을 개발하고 데이터는 로컬 저장에 사용하기 때문에 onUpGrade 방법은 여기에 내용이 없다. 일반적으로 이것은 응용 발표 후 데이터베이스의 필드가 수정되면 해당하는 업그레이드를 하고crash를 사용하지 않도록 한다.onCreate 메서드는 데이터베이스를 만드는 방법입니다.
	@Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_VIDEO = "CREATE TABLE " + TB_VIDEO + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "duration text," + " name text)";
        String CREATE_PHOTO = "CREATE TABLE " + TB_PICTURE + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "size text," + " name text)";
        String CREATE_MUSIC = "CREATE TABLE " + TB_MUSIC + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "duration text," + "music_name text," + " name text)";
        String CREATE_FILE = "CREATE TABLE " + TB_FILE + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "size text," + " name text)";

        db.execSQL(CREATE_MUSIC);
        db.execSQL(CREATE_VIDEO);
        db.execSQL(CREATE_PHOTO);
        db.execSQL(CREATE_FILE);
    }

핵심 방법은db.execSQL(), 즉 데이터베이스에서 SQL을 실행하는 문구, 이곳의 데이터베이스 문구CREATEVIDEO의 뜻은 TB 라는VIDEO의 테이블은 id를 메인 키로 하고 데이터 삽입에 따라 증가하며 네 가지 속성이 수반됩니다:String 형식의 path, int 형식의 type, String 형식의duration,String 형식의name.전체 파일은 다음과 같습니다.
public class DBHelper extends SQLiteOpenHelper {

    private String TAG = DBHelper.class.getSimpleName();

    public static final String DB_NAME = "media.db";

    public static final String TB_VIDEO = "video";
    public static final String TB_PICTURE = "picture";
    public static final String TB_MUSIC = "music";
    public static final String TB_FILE = "file";

    public static final String PATH_KEY = "path";
    public static final String TYPE_KEY = "type";
    public static final String NAME_KEY = "name";
    public static final String DURATION_KEY = "duration";
    public static final String SIZE_KEY = "size";
    public static final String MUSIC_NAME_KEY = "music_name";

    private volatile static DBHelper instance = null;

    private DBHelper(Context context) {
        super(context, DB_NAME, null, 1);
    }

    public static DBHelper getInstance(Context context) {
        if (instance == null) {
            synchronized (DBHelper.class) {
                if (instance == null) {
                    instance = new DBHelper(context);
                }
            }
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_VIDEO = "CREATE TABLE " + TB_VIDEO + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "duration text," + " name text)";
        String CREATE_PHOTO = "CREATE TABLE " + TB_PICTURE + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "size text," + " name text)";
        String CREATE_MUSIC = "CREATE TABLE " + TB_MUSIC + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "duration text," + "music_name text," + " name text)";
        String CREATE_FILE = "CREATE TABLE " + TB_FILE + "(_id INTEGER PRIMARY key autoincrement,"
                + "path text," + "type Integer," + "size text," + " name text)";

        db.execSQL(CREATE_MUSIC);
        db.execSQL(CREATE_VIDEO);
        db.execSQL(CREATE_PHOTO);
        db.execSQL(CREATE_FILE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}


DBHelper는 데이터베이스의 창설과 관리를 책임지고 새로운 Database Util 클래스를 만들어 데이터의 CURD 작업을 수행한다. 먼저 DBHelper의 실례를 얻은 다음에 DBHelper를 통해 SQLite Database 대상을 얻고 최종적으로 SQLite Database 대상에 대한 데이터의 CURD 등 조작을 한다. 여기서 우리는 처음부터 끝까지 데이터베이스에 전송되는 경로가 없다는 것을 알 수 있다.그럼 데이터베이스는 어디에 저장됩니까? dbHelper를 봅시다.getWritable Database()의 코드:
	public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }
    private SQLiteDatabase getDatabaseLocked(boolean writable) {
        //      
        try {
            mIsInitializing = true;

            if (db != null) {
                if (writable && db.isReadOnly()) {
                    db.reopenReadWrite();
                }
            } else if (mName == null) {
                db = SQLiteDatabase.createInMemory(mOpenParamsBuilder.build());
            } else {
                final File filePath = mContext.getDatabasePath(mName);
                SQLiteDatabase.OpenParams params = mOpenParamsBuilder.build();
                try {
                    db = SQLiteDatabase.openDatabase(filePath, params);
                    // Keep pre-O-MR1 behavior by resetting file permissions to 660
                    setFilePermissionsForDb(filePath.getPath());
                } catch (SQLException ex) {
                    if (writable) {
                        throw ex;
                    }
                    Log.e(TAG, "Couldn't open " + mName
                            + " for writing (will try read-only):", ex);
                    params = params.toBuilder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
                    db = SQLiteDatabase.openDatabase(filePath, params);
                }
            }
            onConfigure(db);
			//      
            onOpen(db);
            if (db.isReadOnly()) {
                Log.w(TAG, "Opened " + mName + " in read-only mode");
            }
            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }

데이터베이스가 비어 있을 때 SQLiteDatabase가 실행된 것을 보았습니다.openDatabase(filePath,params) 메서드,final File filePath = mContext.getDatabasePath (mName) 는 Context에서 데이터베이스 경로를 가져오는 방법을 실행하고, 최종적으로 ContextImpl 클래스에서 filepath가 현재 적용되는 데이터 경로를 찾을 수 있습니다.
	@Override
    public File getDatabasePath(String name) {
        File dir;
        File f;
        if (name.charAt(0) == File.separatorChar) {
            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
            dir = new File(dirPath);
            name = name.substring(name.lastIndexOf(File.separatorChar));
            f = new File(dir, name);

            if (!dir.isDirectory() && dir.mkdir()) {
                FileUtils.setPermissions(dir.getPath(),
                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                    -1, -1);
            }
        } else {
            dir = getDatabasesDir();
            f = makeFilename(dir, name);
        }
        return f;
    }
    
	private File getDatabasesDir() {
        synchronized (mSync) {
            if (mDatabasesDir == null) {
                if ("android".equals(getPackageName())) {
                    mDatabasesDir = new File("/data/system");
                } else {
                    mDatabasesDir = new File(getDataDir(), "databases");
                }
            }
            return ensurePrivateDirExists(mDatabasesDir);
        }
    }

다음은 데이터 삽입, 삭제, 조회 등: 삽입:
	public void insertVideoData(VideoData videoData) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(DBHelper.NAME_KEY, videoData.getName());
        contentValues.put(DBHelper.PATH_KEY, videoData.getPath());
        contentValues.put(DBHelper.TYPE_KEY, videoData.getType());
        contentValues.put(DBHelper.DURATION_KEY, videoData.getDurationString());
        sqLiteDatabase.insert(DBHelper.TB_VIDEO, null, contentValues);
    }

질의:
	public List<VideoData> getAllVideoData() {
        Cursor cursor = sqLiteDatabase.query(DBHelper.TB_VIDEO, null, null,
                null, null, null, null);
        ArrayList<VideoData> mainDatas = new ArrayList<>();
        while (cursor.moveToNext()) {
            VideoData videoData = new VideoData();
            videoData.setName(cursor.getString(cursor.getColumnIndex(DBHelper.NAME_KEY)));
            videoData.setPath(cursor.getString(cursor.getColumnIndex(DBHelper.PATH_KEY)));
            videoData.setType(cursor.getInt(cursor.getColumnIndex(DBHelper.TYPE_KEY)));
            videoData.setDurationString(cursor.getString(cursor.getColumnIndex(DBHelper.DURATION_KEY)));
            mainDatas.add(videoData);
        }
        cursor.close();
        return mainDatas;
    }

여기에는 모두 ContentValues가 사용됩니다.
2. 데이터의 모호한 조작
때때로 우리는 특정 조건의 데이터를 삭제하기만 하면 모호하게 삭제해야 한다.
	public void deletePathData(String path) {
        sqLiteDatabase.delete(DBHelper.TB_VIDEO, DBHelper.PATH_KEY + " like ? ",
                new String[]{path + "%"});
        sqLiteDatabase.delete(DBHelper.TB_MUSIC, DBHelper.PATH_KEY + " like ? ",
                new String[]{path + "%"});
        sqLiteDatabase.delete(DBHelper.TB_PICTURE, DBHelper.PATH_KEY + " like ? ",
                new String[]{path + "%"});
        sqLiteDatabase.delete(DBHelper.TB_FILE, DBHelper.PATH_KEY + " like ? ",
                new String[]{path + "%"});
    }

delete 문의 매개 변수에 DBHelper를 전송합니다.PATH_KEY + "like ? ",New String[]{path + "%"}이(가) 좋습니다.KEY 데이터 센터에 지정된 path가 포함된 데이터가 삭제됩니다.데이터베이스의 조작 핵심은 사실 SQL 문장이다. 모든 조회 삭제 등 문장은 SQL 문장을 통해 실현할 수 있다. 단지android는 우리가 사용하는 편리함을 위해 이런 방법을 봉인했다. 우리는 일상적인 업무에서 이런 방법을 사용하면 된다.

좋은 웹페이지 즐겨찾기