데이터 저장 및 액세스 - SQLite 데이터베이스와의 첫 만남


이 섹션 소개:

이 섹션에서 우리는 Android 데이터 저장 및 액세스의 세 번째 방법인 다른 SQL 데이터베이스와 다른 SQLite 데이터베이스를 계속해서 배웁니다. 우리는 휴대폰에 다른 데이터베이스 소프트웨어를 설치할 필요가 없습니다. Android 시스템에는 이 데이터베이스가 통합되어 있습니다. 다른 데이터베이스 소프트웨어(Oracle, MSSQL, MySql 등)를 사용하는 경우 해당 소프트웨어를 설치하고 해당 구성을 완료한 후 포트를 변경해야 합니다! 소개는 여기까지입니다. 다음 내용에 대해 알아봅시다~


1. 기본 개념

1) SQLite란 무엇인가요? 왜 SQLite를 사용하나요? SQLite의 특징은 무엇입니까?

답변: 아래 Xiaozhu의 설명을 들어보세요.

①SQLite는 빠른 컴퓨팅 속도와 낮은 리소스 사용량을 갖춘 경량 관계형 데이터베이스입니다. 표준 SQL 구문을 지원할 뿐만 아니라 ACID(데이터베이스 트랜잭션) 원칙을 따르므로 계정이 필요하지 않으며 사용이 매우 편리합니다!

② 앞에서는 파일과 SharedPreference를 사용하여 데이터를 저장하는 방법을 배웠지만, 많은 경우 파일이 반드시 유효한 것은 아닙니다. 예를 들어 여러 스레드에 의한 동시 액세스는 관련성이 있습니다. 앱은 변경될 수 있는 복잡한 데이터 구조를 처리해야 합니다. 은행에 돈을 입금하고 인출하는 등! 처음 두 가지를 사용하는 것은 매우 무력하거나 번거롭게 보일 것입니다. 데이터베이스의 출현으로 이 문제를 해결할 수 있습니다. 그리고 Android는 이렇게 가벼운 SQLite를 제공하는데 왜 사용하지 않겠습니까?

3SQLite는 다섯 가지 데이터 유형을 지원합니다: NULL, INTEGER, REAL(부동 소수점 수), TEXT(문자열 텍스트) 및 BLOB(이진 개체) 5가지 유형만 있지만 varchar, char 등 다른 데이터 유형도 저장할 수 있습니다. SQLite의 가장 큰 특징은 다음과 같습니다. 필드에서 선언한 데이터 유형을 신경쓰지 않고 어떤 필드에든 다양한 데이터 유형의 데이터를 저장할 수 있습니다. 그게 뭐야, 너처럼? 물론 문자열은 기본 키로 선언하는 것을 제외하고는 정수 유형 필드에 저장할 수 있습니다. INTEGER PRIMARY KEY 필드는 64비트 정수만 저장할 수 있습니다! 또한 SQLite가 CREATE TABLE 문을 구문 분석할 때, CREATE TABLE 문에서 필드 이름 뒤에 오는 데이터 유형 정보는 무시됩니다. 예를 들어 다음 문은 이름 필드의 유형 정보를 무시합니다. CREATE TABLE person (personid 정수 기본 키 자동 증가, name varchar(20))

기능 요약:

SQlite는

files

를 통해 데이터베이스를 저장합니다. 파일은 database이고 데이터베이스에는 여러 개의 테이블이 포함되어 있습니다. 여러 레코드 , 각 레코드는 여러 필드 로 구성되며 각 필드에는 해당 이 있으며 각 값에 대해 유형 을 지정할 수 있습니다. 유형(기본 키 제외)

PS

: 그런데 Android에 내장된 SQLite는 SQLite 3 버전입니다~2) 여러 관련 클래스:

야, 학습할 때 가장 마음에 들지 않습니다. 새로운 용어를 접하는 것보다 더 좋은 것은 없습니다. 먼저 몇 가지에 대해 이야기해 볼까요? 데이터베이스를 사용할 때 사용하는 세 가지 클래스:
  • SQLiteOpenHelper: 추상 클래스, 이 클래스를 상속한 다음 데이터베이스 생성 및 업데이트 메서드를 재정의합니다. 이 클래스의 객체를 통해 데이터베이스 인스턴스를 얻거나 데이터베이스를 닫을 수도 있습니다!
  • SQLiteDatabase: 데이터베이스 액세스 클래스: 이 클래스의 개체를 사용하여 데이터베이스에 대한 추가, 삭제, 수정 및 쿼리 작업을 수행할 수 있습니다.
  • Cursor: 커서, JDBC의 결과 집합과 다소 유사, 결과 집합! 단순히 데이터베이스의 특정 지점을 가리키는 것으로 이해될 수 있습니다. 레코드 포인터!

2. SQLiteOpenHelper 클래스를 사용하여 데이터베이스 생성 및 버전 관리

데이터베이스와 관련된 앱의 경우 데이터베이스 파일을 수동으로 생성하는 것이 불가능하므로 처음으로 앱을 활성화해야 합니다. 데이터베이스 테이블은 애플리케이션이 업그레이드될 때 생성됩니다. 이번에는 애플리케이션을 업그레이드하고 데이터베이스 테이블의 구조를 수정해야 할 때입니다. 데이터베이스 테이블이 업데이트되었습니다. Android는 SQLiteOpenHelper, onCreate( ) 및 onUpgrade( )의 두 가지 메서드를 제공하여

메서드 분석을 구현합니다.

  • onCreate (database): 소프트웨어를 처음 사용할 때 데이터베이스 테이블을 생성합니다.
  • onUpgrade(database, oldVersion, newVersion): 데이터베이스 버전이 변경되면 호출됩니다. 일반적으로 버전 번호는 소프트웨어를 업그레이드할 때만 변경하면 되며, 데이터베이스 버전은 프로그래머가 제어합니다. 버전은 1입니다. 업무 변경으로 인해 데이터베이스 테이블 구조가 수정되었습니다. 이때 소프트웨어 업그레이드가 필요합니다. 사용자 휴대폰의 데이터베이스 테이블 구조를 업데이트하려면 원래 데이터베이스 버전을 2로 설정할 수 있습니다. 아니면 이전 버전 번호와 다른 다른 번호!

코드 예시:

public class MyDBOpenHelper extends SQLiteOpenHelper {
    public MyDBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {super(context, "my.db", null, 1); }
    @Override
    //数据库第一次创建时被调用
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");
        
    }
    //软件版本号发生改变时调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
    }
}

코드 분석:

위 코드가 처음으로 애플리케이션을 시작하면 이 my.db 파일을 생성하고 onCreate()에서 메소드를 실행하게 됩니다. 기본 키 personId와 name 필드라는 두 개의 필드가 있는 Person 테이블을 만든 다음 db 버전을 수정합니다. 번호를 입력하면 다음에 onUpgrade()가 시작될 때 메서드가 호출되고 다른 필드가 테이블에 삽입됩니다! 게다가 여기에 삽입 데이터가 손실되지 않도록 하는 필드입니다. 테이블이 다시 작성되면 다음 섹션에서 테이블의 모든 데이터가 손실됩니다. 이 문제를 해결하는 방법을 가르쳐 드리겠습니다!

프로세스 요약:

  • 1단계: SQLiteOpenHelper 클래스를 상속하도록 클래스를 사용자 정의합니다.
  • 2단계: 클래스 생성자 메서드의 상위에 생성할 데이터베이스 이름과 버전 번호를 설정합니다.
  • 3단계: 재작성 onCreate() 메소드는 테이블 구조를 생성합니다
  • 4단계: 버전 번호 변경 후 수행할 작업을 정의하기 위해 onUpgrade() 메소드를 재작성합니다

3 생성한 db 파일을 보는 방법.

위를 호출하면 MyDBOpenhelper 개체의 getWritableDatabase()가 다음 디렉터리에 db를 생성합니다. 데이터베이스 파일:

8.png

두 개의 데이터베이스가 있음을 발견했습니다. 전자는 우리가 만든 데이터베이스이고 후자는 데이터베이스가 트랜잭션을 지원할 수 있도록 생성되었습니다. 임시 로그 파일! 일반적인 크기는 0바이트입니다! 하지만 파일 탐색기에서는 .db는 물론 txt도 아닌 파일을 열 수 없습니다! 따라서 두 가지 옵션이 있습니다:

  • 1. 먼저 내보낸 다음 SQLite의 그래픽 도구를 사용하여 확인합니다.
  • 2 adb 환경 변수를 구성한 후 adb 쉘(명령줄, 컴파일러 설치)을 통해 확인합니다. )!

자, 위의 두 가지 방법을 보여드리겠으니 마음에 드는 방법을 선택하시면 됩니다~~


방법 1: SQLite 그래픽 도구를 사용하여 db 파일 보기

그런 소프트웨어가 많이 있는데, 저자는 그 중 하나를 사용합니다 SQLite Expert Professional입니다. 물론 다른 도구도 사용할 수 있습니다. 필요한 경우 다운로드할 수 있습니다: SQLiteExpert.zip

db 파일을 컴퓨터 데스크탑으로 내보내고 SQLiteExpert를 엽니다. 인터페이스는 다음과 같습니다.

1.png

플레이 방법을 묻지 말고 가져오세요. db로 혼자 천천히 플레이하는 방법이 아주 쉽습니다 간단하고 바이두가 이해가 안가네요~


두 번째 방법은 원래 해보고 싶었는데 나중에 sqlite 명령어를 찾을 수 없더군요 , 그래서 몇 번 시도해보고 잊어버렸어요. 나중에 미세버튼에 활용될 예정이니 관심 있으신 분들은 Guo Lin의 "The First Line of Code - Android"를 찾아 순서도에 따라 사용해 보세요! 여기에는 첫 번째 부분만 게시되어 있습니다. 명령 부분을 직접 읽어보세요!

방법 2: adb 쉘 명령줄은 가장하고 비행하는 데 도움이 됩니다.

1. SDK 환경 변수 구성:

내 컴퓨터를 마우스 오른쪽 버튼으로 클릭하세요 ——> 변수 -> 새 시스템 변수 생성 -> SDK의 플랫폼 도구 경로를 복사합니다. 예를 들어 작성자는 다음과 같습니다. C:SoftwareCodingandroid-sdks-asplatform-tools

2.png확인하고 Path 환경 변수를 찾아 편집한 후 끝에 %SDK_HOME%;

를 추가합니다.

3.png

그런 다음 명령줄을 열고 adb를 입력하고 여러 가지를 휘두르면 구성이 성공했음을 의미합니다!

——————요점——————: 후속 명령줄 지침을 실행하기 전에 테스트용 컴퓨터가 여러 개 있을 수 있습니다. 1.네이티브 시뮬레이터: 좋습니다. 여기를 건너뛰고 계속하세요. 2.Genymotion 에뮬레이터: 문제 없습니다. Genymotion Shell은 다음 명령을 실행할 수 없습니다. 3.실제 머신(루팅): 그런 다음 파일 탐색기를 열고 data/data/ 디렉토리에 아무것도 없는지 확인하세요. 아니요? 다음 방법은 먼저 RE 파일 관리자를 설치한 다음 RE 루트 권한을 부여한 다음 루트 디렉터리로 이동하는 것입니다. 그런 다음 데이터 디렉터리를 길게 누르면 다음과 같은 대화 상자가 나타납니다.

4.png10.png

5.png

그런 다음 수정이 완료되면 DDMS의 파일 탐색기를 다시 엽니다. , 그리고 우리는 다음을 볼 수 있습니다:

6.png

좋아요, 데이터/데이터에 있는 것들을 볼 수 있습니다! —————————————————————

2. adb 쉘을 입력한 후 다음 명령을 입력하여 앱의 데이터베이스 디렉터리로 이동하세요.

7.png

그런 다음 다음 명령을 순서대로 입력합니다.

  • sqlite3 my.db: 데이터베이스 파일
  • .table을 열어 데이터베이스에 어떤 테이블이 있는지 확인합니다. 그런 다음 쿼리와 같은 데이터베이스 문을 직접 입력할 수 있습니다. Select * from person
  • .schema: 테이블 생성 문 보기
  • .quit: 데이터베이스 편집 종료
  • .exit: 장치 종료 console

... system/bin/sh sqlite3: notfound 때문에 이 문제는 후속 Sqlite 명령을 사용할 수 없음을 의미합니다. 렌더링을 보고 싶으시면 Guo Daxia의 책을 직접 확인해 보세요~ 하지만 아래에서는 db 파일을 먼저 내보낸 다음 그래픽을 사용하겠습니다. 볼 수 있는 데이터베이스 도구!


4. 안드로이드에서 제공하는 API를 사용해 SQLite

데이터베이스 관련 구문을 배우지 않았거나, 게으르고 데이터베이스 구문을 작성하기 싫다면 안드로이드를 사용해도 됩니다. 데이터베이스 운영을 위한 몇 가지 API 메소드를 제공합니다. 이러한 API의 사용법을 다루는 간단한 예제를 작성해 보겠습니다.

코드 예:

렌더링 실행:

8.gif

구현 코드:

레이아웃이 너무 간단하고, 버튼이 4개밖에 없어서 붙여넣지 않고 MainActivity.java 코드를 직접 붙여넣습니다.

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private Button btn_insert;
    private Button btn_query;
    private Button btn_update;
    private Button btn_delete;
    private SQLiteDatabase db;
    private MyDBOpenHelper myDBHelper;
    private StringBuilder sb;
    private int i = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        myDBHelper = new MyDBOpenHelper(mContext, "my.db", null, 1);
        bindViews();
    }

    private void bindViews() {
        btn_insert = (Button) findViewById(R.id.btn_insert);
        btn_query = (Button) findViewById(R.id.btn_query);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);

        btn_query.setOnClickListener(this);
        btn_insert.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        db = myDBHelper.getWritableDatabase();
        switch (v.getId()) {
            case R.id.btn_insert:
                ContentValues values1 = new ContentValues();
                values1.put("name", "呵呵~" + i);
                i++;
                //参数依次是:表名,强行插入null值得数据列的列名,一行记录的数据
                db.insert("person", null, values1);
                Toast.makeText(mContext, "插入完毕~", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_query:
                sb = new StringBuilder();
                //参数依次是:表名,列名,where约束条件,where中占位符提供具体的值,指定group by的列,进一步约束
                //指定查询结果的排序方式
                Cursor cursor = db.query("person", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        int pid = cursor.getInt(cursor.getColumnIndex("personid"));
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        sb.append("id:" + pid + ":" + name + "\n");
                    } while (cursor.moveToNext());
                }
                cursor.close();
                Toast.makeText(mContext, sb.toString(), Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                ContentValues values2 = new ContentValues();
                values2.put("name", "嘻嘻~");
                //参数依次是表名,修改后的值,where条件,以及约束,如果不指定三四两个参数,会更改所有行
                db.update("person", values2, "name = ?", new String[]{"呵呵~2"});
                break;
            case R.id.btn_delete:
                //参数依次是表名,以及where条件与约束
                db.delete("person", "personid = ?", new String[]{"3"});
                break;
        }
    }
}

5. SQL 문을 사용해 데이터베이스를 운영하세요

물론, 이미 SQL을 배워서 관련 SQL 문을 작성할 수 있지만 Android에서 제공하는 이러한 API를 사용하고 싶지 않을 수도 있습니다. SQLiteDatabase에서 제공하는 관련 메소드를 직접 사용할 수 있습니다:

  • execSQL(SQL, Object[]): 자리 표시자가 있는 SQL 문을 사용합니다. 데이터베이스 내용을 수정하는 SQL 문을 실행하는 데 사용됩니다
  • rawQuery (SQL, Object[]): 자리 표시자와 함께 SQL 쿼리 작업을 사용합니다. 또한 앞서 Curosr 및 관련 속성을 소개하는 것을 잊어버렸습니다. —— Cursor 객체는 JDBC의 ResultSet과 다소 비슷하며 사용법도 비슷합니다. 다음은 쿼리 결과의 레코드 포인터를 이동하는 방법입니다.
  • move(오프셋): 위 또는 아래로 이동할 행 수, 정수 아래로 이동하는 것을 의미합니다. 음수는 위로 이동하는 것을 의미합니다.
  • moveToFirst(): 포인터가 첫 번째 행으로 이동하고 true를 성공적으로 반환합니다. 이는 또한 데이터가 있음을 나타냅니다.
  • moveToLast(): 포인터가 마지막 행으로 이동하고 true를 성공적으로 반환합니다.
  • moveToNext(): 포인터 다음 줄로 이동하고 true를 성공적으로 반환하여 아직 요소가 있음을 나타냅니다!
  • moveToPrevious(): 이전 레코드로 이동
  • getCount( )하여 전체 데이터 수 가져오기
  • isFirst(): 첫 번째 레코드인지 여부
  • isLast(): 여부 마지막 1개 항목입니다.
  • moveToPosition(int): 지정된 행으로 이동

사용 코드 예:

1. 데이터 삭제:

public void save(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("INSERT INTO person(name,phone) values(?,?)",
                new String[]{p.getName(),p.getPhone()});
}

3. :

public void delete(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("DELETE FROM person WHERE personid = ?",
                new String[]{id});
}

4 .쿼리 데이터:

public void update(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("UPDATE person SET name = ?,phone = ? WHERE personid = ?",
        new String[]{p.getName(),p.getPhone(),p.getId()});
}

5. 데이터 페이징:

public Person find(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person WHERE personid = ?",
            new String[]{id.toString()});
    //存在数据才返回true
    if(cursor.moveToFirst())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        return new Person(personid,name,phone);
    }
    cursor.close();
    return null;
}

6. 쿼리 레코드 번호:

public List<Person> getScrollData(int offset,int maxResult)
{
    List<Person> person = new ArrayList<Person>();
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",
        new String[]{String.valueOf(offset),String.valueOf(maxResult)});
    while(cursor.moveToNext())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        person.add(new Person(personid,name,phone)) ;
    }
    cursor.close();
    return person;
}

PS

: 레코드 수를 얻는 위의 방법 외에도 다음을 사용할 수 있습니다. 데이터의 개수를 얻기 위한cursor.getCount() 메소드, 하지만 SQL 문을 변경해야 합니다! 예를 들어 SELECT * FROM person;

이 섹션 요약:

이 섹션에서는 Android에 내장된 SQLite의 기본 사용법을 소개합니다. 다음 섹션에서는 비교적 간단합니다. . 고급 기능, SQLite 트랜잭션, 애플리케이션이 업데이트할 때 데이터베이스에서 데이터를 처리하는 방법, 데이터베이스에 대용량 바이너리 파일을 저장하는 방법 방법! 좋아요, 이번 섹션은 여기까지입니다~