Перейти к содержимому

Как подключить sqlite к android studio

  • автор:

Работа с базами данных SQLite

В Android имеется встроенная поддержка одной из распространенных систем управления базами данных — SQLite. Для этого в пакете android.database.sqlite определен набор классов, которые позволяют работать с базами данных SQLite. И каждое приложение может создать свою базу данных.

Чтобы использовать SQLite в Android, надо создать базу данных с помощью выражение на языке SQL. После этого база данных будет храниться в каталоге приложения по пути:

DATA/data/[Название_приложения]/databases/[Название_файла_базы_данных]

ОС Android по умолчанию уже содержит ряд встроенных бад SQLite, которые используются стандартными программами — для списка контактов, для хранения фотографий с камеры, музыкальных альбомов и т.д.

Основную функциональность по работе с базами данных предоставляет пакет android.database . Функциональность непосредственно для работы с SQLite находится в пакете android.database.sqlite .

База данных в SQLite представлена классом android.database.sqlite.SQLiteDatabase . Он позволяет выполнять запросы к бд, выполнять с ней различные манипуляции.

Класс android.database.sqlite.SQLiteCursor предоставляет запрос и позволяет возвращать набор строк, которые соответствуют этому запросу.

Класс android.database.sqlite.SQLiteQueryBuilder позволяет создавать SQL-запросы.

Сами sql-выражения представлены классом android.database.sqlite.SQLiteStatement , которые позволяют с помощью плейсхолдеров вставлять в выражения динамические данные.

Класс android.database.sqlite.SQLiteOpenHelper позволяет создать базу данных со всеми таблицами, если их еще не существует.

В SQLite применяется следующая система типов данных:

  • INTEGER : представляет целое число, аналог типу int в java
  • REAL : представляет число с плавающей точкой, аналог float и double в java
  • TEXT : представляет набор символов, аналог String и char в java
  • BLOB : представляет массив бинарных данных, например, изображение, аналог типу int в java

Сохраняемые данные должны представлять соответствующие типы в java.

Создание и открытие базы данных

Для создания или открытия новой базы данных из кода Activity в Android мы можем вызвать метод openOrCreateDatabase() . Этот метод может принимать три параметра:

  • название для базы данных
  • числовое значение, которое определяет режим работы (как правило, в виде константы MODE_PRIVATE )
  • необязательный параметр в виде объекта SQLiteDatabase.CursorFactory , который представляет фабрику создания курсора для работы с бд

Например, создание базы данных app.db :

SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null);

Для выполнения запроса к базе данных можно использовать метод execSQL класса SQLiteDatabase. В этот метод передается SQL-выражение. Например, создание в базе данных таблицы users:

SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)");

Если нам надо не просто выполнить выражение, но и получить из бд какие-либо данные, то используется метод rawQuery() . Этот метод в качестве параметра принимает SQL-выражение, а также набор значений для выражения sql. Например, получение всех объектов из базы данных:

SQLiteDatabase db = getBaseContext().openOrCreateDatabase(«app.db», MODE_PRIVATE, null); db.execSQL(«CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER)»); Cursor query = db.rawQuery(«SELECT * FROM users;», null); if(query.moveToFirst())

Метод db.rawQuery() возвращает объект Cursor, с помощью которого мы можем извлечь полученные данные.

Возможна ситуация, когда в базе данных не будет объектов, и для этого методом query.moveToFirst() пытаемся переместиться к первому объекту, полученному из бд. Если этот метод возвратит значение false, значит запрос не получил никаких данных из бд.

Теперь для работы с базой данных сделаем простейшее приложение. Для этого создадим новый проект.

В файле activity_main.xml определим простейший графический интерфейс:

А в классе MainActivity определим взаимодействие с базой данных:

package com.example.sqliteapp; import androidx.appcompat.app.AppCompatActivity; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >public void onClick(View view) < SQLiteDatabase db = getBaseContext().openOrCreateDatabase("app.db", MODE_PRIVATE, null); db.execSQL("CREATE TABLE IF NOT EXISTS users (name TEXT, age INTEGER, UNIQUE(name))"); db.execSQL("INSERT OR IGNORE INTO users VALUES ('Tom Smith', 23), ('John Dow', 31);"); Cursor query = db.rawQuery("SELECT * FROM users;", null); TextView textView = findViewById(R.id.textView); textView.setText(""); while(query.moveToNext())< String name = query.getString(0); int age = query.getInt(1); textView.append("Name: " + name + " Age: " + age + "\n"); >query.close(); db.close(); > >

По нажатию на кнопку здесь вначале создается в базе данных app.db новая таблица users, а затем в нее добавляются два объекта в базу данных с помощью SQL-выражения INSERT.

Далее с помощью выражения SELECT получаем всех добавленных пользователей из базы данных в виде курсора Cursor.

Вызовом query.moveToNext() перемещаемся в цикле while последовательно по всем объектам.

Для получения данных из курсора применяются методы query.getString(0) и query.getInt(1) . В скобках в методы передается номер столбца, из которого мы получаем данные. Например, выше мы добавили вначале имя пользователя в виде строки, а затем возраст в виде числа. Значит, нулевым столбцом будет идти строкое значение, которое получаем с помощью метода getString() , а следующим — первым столбцом идет числовое значение, для которого применяется метод getInt() .

После завершения работы с курсором и базой данных мы закрываем все связанные объекты:

query.close(); db.close();

Если мы не закроем курсор, то можем столкнуться с проблемой утечки памяти.

И если мы обратимся к приложению, то после нажатия на кнопку в текстовое поле будут выведены добавленные данные:

Подключение существующей БД SQLite в Android Studio (кратко)

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

Подготовка файла базы данных SQLite

Для создания SQLite базы данных я рекомендую использовать DB Browser for SQLite. Скачайте и установите. Создайте базу данных в виде файла и сохраните его.

Добавьте файл базы данных в папку assets .

Класс для подключения к базе данных

Данный класс позволяет не только копировать существующую базу данных, но и обновлять ее в соответствии с номером версии базы данных:

//package org.harrix.sqliteexample; import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class DatabaseHelper extends SQLiteOpenHelper  private static String DB_NAME = "info.db"; private static String DB_PATH = ""; private static final int DB_VERSION = 1; private SQLiteDatabase mDataBase; private final Context mContext; private boolean mNeedUpdate = false; public DatabaseHelper(Context context)  super(context, DB_NAME, null, DB_VERSION); if (android.os.Build.VERSION.SDK_INT >= 17) DB_PATH = context.getApplicationInfo().dataDir + "/databases/"; else DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; this.mContext = context; copyDataBase(); this.getReadableDatabase(); > public void updateDataBase() throws IOException  if (mNeedUpdate)  File dbFile = new File(DB_PATH + DB_NAME); if (dbFile.exists()) dbFile.delete(); copyDataBase(); mNeedUpdate = false; > > private boolean checkDataBase()  File dbFile = new File(DB_PATH + DB_NAME); return dbFile.exists(); > private void copyDataBase()  if (!checkDataBase())  this.getReadableDatabase(); this.close(); try  copyDBFile(); > catch (IOException mIOException)  throw new Error("ErrorCopyingDataBase"); > > > private void copyDBFile() throws IOException  InputStream mInput = mContext.getAssets().open(DB_NAME); // InputStream mInput = mContext.getResources().openRawResource(R.raw.info); OutputStream mOutput = new FileOutputStream(DB_PATH + DB_NAME); byte[] mBuffer = new byte[1024]; int mLength; while ((mLength = mInput.read(mBuffer)) > 0) mOutput.write(mBuffer, 0, mLength); mOutput.flush(); mOutput.close(); mInput.close(); > public boolean openDataBase() throws SQLException  mDataBase = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.CREATE_IF_NECESSARY); return mDataBase != null; > @Override public synchronized void close()  if (mDataBase != null) mDataBase.close(); super.close(); > @Override public void onCreate(SQLiteDatabase db)  > @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  if (newVersion > oldVersion) mNeedUpdate = true; > >: 

Использование класса

В классе активности объявите переменные:

private DatabaseHelper mDBHelper; private SQLiteDatabase mDb; 

В методе onCreate пропишите следующий код:

mDBHelper = new DatabaseHelper(this); try  mDBHelper.updateDataBase(); > catch (IOException mIOException)  throw new Error("UnableToUpdateDatabase"); > try  mDb = mDBHelper.getWritableDatabase(); > catch (SQLException mSQLException)  throw mSQLException; > 

Файл базы данных в папке res/raw

Если вы добавляете файл базы данных в папку ‘res/raw`, то используйте следующую модификацию класса:

«`java //package org.harrix.sqliteexample;

import android.content.Context; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;

import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

В статье представлен класс для использования существующей базы данных SQLite. Данный класс позволяет обновлять базу данных через переменную DB_VERSION.

Harrix

  • GitHub User
  • [email protected]

Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description.

Как подключить внешнюю базу данных SQLite в Android?

Таблица есть — проверял через DB Browser,через него и создавал базу.

Я так понимаю, он просто не видит эту базу данных. Кидаю базу в assets (меня смутило, что не было этой папки в Android Studio 1.5.1 — создал с помощью New/ Assets Folder).

Использую этот код. Тестирую на Android 4.1

Отслеживать
задан 3 фев 2016 в 15:24
Denis Ivanov Denis Ivanov
55 1 1 серебряный знак 4 4 бронзовых знака
Возможно разрешения не хватает на чтение с диска в манифесте.
3 фев 2016 в 16:09
@ЮрийСПб, про разрешения совсем забыл
3 фев 2016 в 19:44

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

  1. Положил БД в папку assets
  2. У меня есть класс для работы с БД import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream;

import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper;

public class ExternalDbOpenHelper extends SQLiteOpenHelper

//Путь к папке с базами на устройстве public static String DB_PATH; //Имя файла с базой public static String DB_NAME; public SQLiteDatabase database; public final Context context; //private boolean flagdel = true; public SQLiteDatabase getDb() < return database; >public ExternalDbOpenHelper(Context context, String databaseName) < super(context, databaseName, null, 1); this.context = context; //Составим полный путь к базам для нашего приложения DB_PATH = context.getDatabasePath(databaseName).getAbsolutePath(); DB_NAME = databaseName; openDataBase(); >/**Создаст базу, если она не создана и откроет ее*/ public void createDataBase() < boolean dbExist = checkDataBase(); if (!dbExist) < this.getReadableDatabase();//Создает и/или открывает базу данных try catch (IOException e) < throw new Error("Error copying database!"); >> > /**Проверка существования базы данных*/ private boolean checkDataBase() < SQLiteDatabase checkDb = null; String path = DB_PATH + DB_NAME; try < checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY); >catch (SQLiteException e) <> //Андроид не любит утечки ресурсов, все должно закрываться if (checkDb != null) checkDb.close(); return checkDb != null; > /**метод проверки наличия в БД таблицы*/ public boolean checkTableInDB(String nameTable)< boolean result = false; Cursor cur = database.query("sqlite_master", new String[], "type=? AND name=?", new String[], null, null, null); cur.moveToLast(); if(cur.getCount()>0) result = true; cur.close(); return result; > /**метод проверки наличия поля в таблице*/ public boolean checkFieldInTable(String nameTable, String nameField)< boolean result = false; try< Cursor cur = database.rawQuery("PRAGMA table_info('"+nameTable+"')", null); cur.moveToFirst(); while(!cur.isAfterLast()) < String name = ""; trycatch(IllegalArgumentException e)<> if(name.equals(nameField)) < result = true; break; >cur.moveToNext(); > cur.close(); cur = null; >catch(SQLException e)<> return result; > /**Метод копирования базы*/ private void copyDataBase() throws IOException < // Открываем поток для чтения из уже созданной нами БД источник в assets InputStream externalDbStream = context.getAssets().open(DB_NAME); // Путь к уже созданной пустой базе в андроиде String outFileName = DB_PATH + DB_NAME; // Теперь создадим поток для записи в эту БД побайтно OutputStream localDbStream = new FileOutputStream(outFileName); // Собственно, копирование byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = externalDbStream.read(buffer)) >0) < localDbStream.write(buffer, 0, bytesRead); >// Мы будем хорошими мальчиками (девочками) и закроем потоки localDbStream.close(); externalDbStream.close(); > /** Метод получения всех данных из таблицы*/ public Cursor getAllData(String dbTable) < return database.query(dbTable, null, null, null, null, null, null); >/** Метод получения данных из таблицы по условию*/ public Cursor getDataByWhere(String table, String[] columns, String where, String[] where_args) < return database.query(table, columns, where, where_args, null, null, null); >/**Метод открытия БД*/ public SQLiteDatabase openDataBase() throws SQLException < String path = DB_PATH + DB_NAME; if (database == null) < createDataBase(); database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE); >return database; > @Override public synchronized void close() < if (database != null) < database.close(); >super.close(); > @Override public void onCreate(SQLiteDatabase db) <> @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) <> 

    Получаю данные в любом нужном мне месте кода. Ниже метод получения данных. Смысл в том, что если БД с определенной версией не найдена, то она будет скопирована в папку с установленным приложением и далее получена на нее ссылка с дальнейшим использованием. Очень удобно. Советую.

private void getDataFromDB()< ExternalDbOpenHelper dbOpenHelper = new ExternalDbOpenHelper(context, DB_NAME); SQLiteDatabase db = dbOpenHelper.getDb(); String orderby = MeData.getOrderBy(); String table = (!mode.equals(MODE_PREV))?MeData.getTable():MeData.getTable_prev(); String columns[] = MeData.getColumns(); Cursor cur = null; trycatch(Exception e) < if(cur != null) cur.close(); cur= null; if(db != null) db.close(); db = null; if(dbOpenHelper != null) dbOpenHelper.close(); dbOpenHelper = null; return; >cur.moveToFirst(); while(!cur.isAfterLast()) < try< int ND = cur.getInt(cur.getColumnIndex("ND")); int NM = cur.getInt(cur.getColumnIndex("NM")); int NY = cur.getInt(cur.getColumnIndex("NY")); >catch(Exception e) <> cur.moveToNext(); > if(cur != null) cur.close(); cur= null; if(db != null) db.close(); db = null; if(dbOpenHelper != null) dbOpenHelper.close(); dbOpenHelper = null; 

P.S. Не могу толком вставить код. прошу прощения, разберетесь.

Использование простой базы данных SQLite в Android-приложении

В этом руководстве я подробно расскажу о том, как использовать базу данных Android SQLite .

Обновлено: 2022-04-18 17:25:13 Вадим Дворников автор материала

Что такое SQLite

SQLite — это система управления реляционными базами данных, похожая на Oracle , MySQL , PostgreSQL и SQL Server . Она реализует большую часть стандарта SQL , но в отличие от четырех упомянутых выше СУБД она не поддерживает модель « клиент-сервер ». Скорее, она встроена в конечную программу. Это означает, что можно связать базу данных SQLite с приложением и получить доступ ко всем возможностям БД в своем приложении.

Что такое SQLite

Данная СУБД совместима как с Android , так и с iOS , и каждое приложение может создавать и использовать базу данных SQLite . В Android контакты и медиа хранятся и ссылаются на БД SQLite . Она является наиболее используемой СУБД в мире и самым распространенным программным обеспечением. Чтобы узнать о базах данных SQLite как можно больше, посетите официальный сайт SQLite.

Подготовка

Чтобы включить привязку данных в приложении, нужно добавить в файл build.gradle следующий код:

dataBinding.enabled = true

Чтобы использовать как RecyclerView , так и CardView для отображения списков, нужно включить соответствующие библиотеки в разделе зависимостей в файле build.gradle :

dependencies

Чтобы задействовать все возможности базы данных SQLite , лучше изучить синтаксис SQL .

Описание примера приложения

В нашем Android SQLite примере мы создадим две таблицы: Employer и Employee . Таблица Employee будет содержать ссылку на внешний ключ таблицы Employer . Мы рассмотрим, как вставлять, выбирать, обновлять и удалять строки из таблиц. Я также продемонстрирую, как вывести элементы, выбранные из базы данных SQLite в RecyclerView ( список ) и в Spinner .

У нас есть MainActivity , из которого можно перейти к EmployerActivity ( для работы с таблицей Employer ) или к EmployeeActivity ( для работы с таблицей Employee ):

Описание примера приложения

Классы хранения базы данных SQLite

Классы определяют то, как данные хранятся в базе. SQLite сохраняют значения с помощью пяти доступных классов хранения:

  • NULL — нулевое значение;
  • INTEGER — для целых чисел, содержащих от 1 до 8 байтов;
  • REAL — числа с плавающей запятой;
  • TEXT — текстовые строки, хранящиеся с использованием кодировки базы данных ( UTF-8 или UTF-16 );
  • BLOB — двоичные данные, хранящиеся точно так, как они были введены.

Определение таблиц

Поскольку база данных SQLite является локальной, нужно обеспечить, чтобы приложение создавало таблицы и по мере необходимости сбрасывало их.

Начнем с Android SQLite query создания таблицы Employer , а затем перейдем к EmployerActivity .

Рекомендуется размещать логику создания базы х SQLite в классе. Это облегчает устранение возможных неполадок. Назовем наш класс SampleDBContract :

public final class SampleDBContract < private SampleDBContract() < >public static class Employer implements BaseColumns < public static final String TABLE_NAME = "employer"; public static final String COLUMN_NAME = "name"; public static final String COLUMN_DESCRIPTION = "description"; public static final String COLUMN_FOUNDED_DATE = "date"; public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + COLUMN_NAME + " TEXT, " + COLUMN_DESCRIPTION + " TEXT, " + COLUMN_FOUNDED_DATE + " INTEGER" + ")"; >>

Мы определяем частный конструктор для SampleDBContract , а затем создаем класс для представления таблицы Employer . Обратите внимание: класс Employer реализует интерфейс BaseColumns . Он предоставляет два столбца в нашей таблице. Это столбец _ID , который будет автоматически увеличиваться при добавлении каждой новой строки. И столбец _COUNT , который может использоваться ContentProviders для возврата количества записей, извлекаемых через запрос. Столбец _COUNT не является обязательным. Строка CREATE_TABLE компилируется в следующий оператор SQL :

CREATE TABLE IF NOT EXISTS employer (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, date INTEGER)

На данный момент в нашем Android SQLite примере мы определили схему таблицы Employer .

Создание базы данных с помощью SQLiteOpenHelper

Самый простой способ управления созданием базы данных и версиями — создать подкласс SQLiteOpenHelper . Он упрощает управление базой данных SQLite , создавая БД, если они не существуют. Необходимо только переопределить методы onCreate() и onUpgrade() , чтобы указать нужное действие для создания или обновления базы данных:

public class SampleDBSQLiteHelper extends SQLiteOpenHelper < private static final int DATABASE_VERSION = 1; public static final String DATABASE_NAME = "sample_database"; public SampleDBSQLiteHelper(Context context) < super(context, DATABASE_NAME, null, DATABASE_VERSION); >@Override public void onCreate(SQLiteDatabase sqLiteDatabase) < sqLiteDatabase.execSQL(SampleDBContract.Employer.CREATE_TABLE); >@Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employer.TABLE_NAME); onCreate(sqLiteDatabase); >>

Теперь в нашем примере Android database SQLite задаем для нашей базы данных SQLite имя ( sample_database ). Конструктор вызывает конструктор суперкласса с именем и версией базы данных. В onCreate мы указываем объекту SQLiteDatabase выполнить оператор Employer CREATE_TABLE SQL . Через onUpgrade мы сбрасываем таблицу Employer и создаем ее снова:

Создание базы данных с помощью SQLiteOpenHelper

Таблица Employer имеет три столбца: name , description и founded_date . Нажатие кнопки сохранения вызывает метод saveToDB() :

Создание базы данных с помощью SQLiteOpenHelper - 2

В saveToDB() мы получаем ссылку на объект SQLiteDatabase , используя метод getWritableDatabase() из SQLiteOpenHelper . Этот метод создает базу данных, если она еще не существует, или открывает ее, если она уже создана. GetWritableDatabase возвращает объект SQLiteDatabase , который открывает доступ на чтение / запись:

private void saveToDB() < SQLiteDatabase database = new SampleDBSQLiteHelper(this).getWritableDatabase(); ContentValues values = new ContentValues(); values.put(SampleDBContract.Employer.COLUMN_NAME, binding.nameEditText.getText().toString()); values.put(SampleDBContract.Employer.COLUMN_DESCRIPTION, binding.descEditText.getText().toString()); try < Calendar calendar = Calendar.getInstance(); calendar.setTime((new SimpleDateFormat("dd/MM/yyyy")).parse( binding.foundedEditText.getText().toString())); long date = calendar.getTimeInMillis(); values.put(SampleDBContract.Employer.COLUMN_FOUNDED_DATE, date); >catch (Exception e) < Log.e(TAG, "Error", e); Toast.makeText(this, "Date is in the wrong format", Toast.LENGTH_LONG).show(); return; >long newRowId = database.insert(SampleDBContract.Employer.TABLE_NAME, null, values); Toast.makeText(this, "The new Row Id is " + newRowId, Toast.LENGTH_LONG).show(); >

В приведенном выше фрагменте кода есть четыре момента:

  1. Мы получаем объект SQLiteDatabase , который открывает доступ на запись в базу данных;
  2. Значения, которые будут храниться в базе данных, помещаются в объект ContentValue с именем столбца в качестве ключа;
  3. Мы помещаем Date в объект ContentValue , который переводится в класс хранения данных Android SQLite INTEGER ;
  4. При вставке строки в базу данных с помощью метода database.insert() возвращается идентификатор строки.

Выбор данных из базы данных SQLite

Подобно тому, как мы применили метод getWritableDatabase() , можно вызвать getReadableDatabase() объекта SQLiteOpenHelper для получения объекта SQLiteDatabase , который можно использовать для чтения информации из базы данных. Стоит отметить, что объект SQLiteDatabase , возвращаемый getReadableDatabase() , предоставляет собой тот же самый доступ на чтение / запись в базу данных, который был возвращен функцией getWritableDatabase() , за исключением тех случаев, когда существуют определенные ограничения. Например, файловая система, содержащая заполненную базу данных, и база данных может быть открыта только для чтения.

Метод readFromDB будет запрашивать БД, и возвращать все строки из таблицы Employer , в которых имя или описание из таблицы Employer совпадает со значением, введенным в EditText . А также строки, в которых дата основания компании совпадает со значением, введенным в EditText :

private void readFromDB() < String name = binding.nameEditText.getText().toString(); String desc = binding.descEditText.getText().toString(); long date = 0; try < Calendar calendar = Calendar.getInstance(); calendar.setTime((new SimpleDateFormat("dd/MM/yyyy")).parse( binding.foundedEditText.getText().toString())); date = calendar.getTimeInMillis(); >catch (Exception e) <> SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); String[] projection = < SampleDBContract.Employer._ID, SampleDBContract.Employer.COLUMN_NAME, SampleDBContract.Employer.COLUMN_DESCRIPTION, SampleDBContract.Employer.COLUMN_FOUNDED_DATE >; String selection = SampleDBContract.Employer.COLUMN_NAME + " like ? and " + SampleDBContract.Employer.COLUMN_FOUNDED_DATE + " > ? and " + SampleDBContract.Employer.COLUMN_DESCRIPTION + " like ?"; String[] selectionArgs = ; Cursor cursor = database.query( SampleDBContract.Employer.TABLE_NAME, // Запрашиваемая таблица projection, // Возвращаемый столбец selection, // Столбец для условия WHERE selectionArgs, // Значение для условия WHERE null, // не группировать строки null, // не фильтровать по группам строк null // не сортировать ); Log.d(TAG, "The total cursor count is " + cursor.getCount()); binding.recycleView.setAdapter(new SampleRecyclerViewCursorAdapter(this, cursor)); >

В коде Android SQLite query , приведенного выше, projection является массивом String , представляющим столбцы, которые мы хотим получить. selection является строковым представлением условия SQL WHERE , отформатированным таким образом, что символ ‘?’ будет заменен аргументами в массиве selectionArgs String . Вы также можете группировать, фильтровать и сортировать результаты запроса. Вставка данных в базу SQLite с использованием описанного выше метода защищает от SQL-инъекций .

Обратите внимание на объект, возвращаемый запросом — Cursor . В следующем разделе мы покажем, как вывести содержимое Cursor с помощью RecyclerView .

Отображение содержимого объекта Cursor в RecyclerView

Cursor предоставляет произвольный доступ к набору результатов, возвращаемому запросом к базе данных. Это означает, что через Cursor можно получить доступ к значениям в любом месте, подобно Java-спискам или массивам. Благодаря этому приему можно реализовать RecyclerView с использованием Cursor так же, как мы реализуем RecyclerView с помощью ArrayLists . Вместо вызова List.get(i) , вы перемещаете Cursor в нужную позицию, используя moveToPosition() . После этого вызываете соответствующий метод getXXX(int columnIndex) , где XXX — это Blob , Double , Float , Int , Long , Short или String .

Чтобы не беспокоиться о корректных индексах столбцов из метода readFromDB() , примененного выше, мы используем метод getColumnIndexOrThrow() , который извлекает индекс указанного столбца или генерирует исключение, если имя столбца не существует внутри объекта Cursor :

public class SampleRecyclerViewCursorAdapter extends RecyclerView.Adapter  < Context mContext; Cursor mCursor; public SampleRecyclerViewCursorAdapter(Context context, Cursor cursor) < mContext = context; mCursor = cursor; >public static class ViewHolder extends RecyclerView.ViewHolder < EmployerListItemBinding itemBinding; public ViewHolder(View itemView) < super(itemView); itemBinding = DataBindingUtil.bind(itemView); >public void bindCursor(Cursor cursor) < itemBinding.nameLabel.setText(cursor.getString( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_NAME) )); itemBinding.descLabel.setText(cursor.getString( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_DESCRIPTION) )); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(cursor.getLong( cursor.getColumnIndexOrThrow(SampleDBContract.Employer.COLUMN_FOUNDED_DATE))); itemBinding.foundedLabel.setText(new SimpleDateFormat("dd/MM/yyyy").format(calendar.getTime())); >> @Override public int getItemCount() < return mCursor.getCount(); >@Override public void onBindViewHolder(ViewHolder holder, int position) < mCursor.moveToPosition(position); holder.bindCursor(myCursor); >@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) < View view = LayoutInflater.from(parent.getContext()).inflate( R.layout.employer_list_item, parent, false); ViewHolder viewHolder = new ViewHolder(view); return viewHolder; >>

Отображение содержимого объекта Cursor в RecyclerView

Определение внешних ключей

На данный момент в нашем Android SQLite примере мы создали таблицу Employer , которую заполнили строками. Теперь создадим таблицу Employee , которая связана с таблицей Employer через столбец _ID Employer . Мы определяем класс Employee , который расширяет BaseColumns в классе SampleDBContract . Обратите внимание, что при создании таблицы Employee использовали » FOREIGN KEY(employer_id) REFERENCES employer(_id) «:

public static class Employee implements BaseColumns

Обновление SQLiteOpenHelper

На данный момент в Android Studio SQLite у вас должна быть создана таблица Employer и в нее добавлены значения. Если вы не изменяете версию базы данных, новая таблица Employee не будет создана. К сожалению, если вы измените версию через повторный вызов метода onUpgrade() , то таблица Employer будет сброшена. Чтобы предотвратить это, можно закомментировать или удалить оператор drop в методе onUpgrade() и добавить оператор execSQL() для создания таблицы Employee . Поскольку таблица Employee ссылается на таблицу Employer , сначала необходимо создать таблицу Employer :

public class SampleDBSQLiteHelper extends SQLiteOpenHelper < private static final int DATABASE_VERSION = 2; public static final String DATABASE_NAME = "sample_database"; public SampleDBSQLiteHelper(Context context) < super(context, DATABASE_NAME, null, DATABASE_VERSION); >@Override public void onCreate(SQLiteDatabase sqLiteDatabase) < sqLiteDatabase.execSQL(SampleDBContract.Employer.CREATE_TABLE); sqLiteDatabase.execSQL(SampleDBContract.Employee.CREATE_TABLE); >// Мы не хотим удалять данные пользователей. @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) < if(oldVersion == 0 && newVersion == 2) < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employee.TABLE_NAME); >else < sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employer.TABLE_NAME); sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + SampleDBContract.Employee.TABLE_NAME); >onCreate(sqLiteDatabase); > >

Отображение данных из запроса SQLite в Spinner

Чтобы создать работника в таблице Employee , пользователю необходимо выбрать соответствующего работодателя в таблице Employer . Для этого можно предоставить пользователю Spinner . Отобразить содержимое Cursor в Spinner довольно просто.

Сначала мы выполняем Android SQLite query , как было описано выше, выбираем только name из Employer и id (queryCols) . Затем создаем экземпляр SimpleCursorAdapter , передавая ему Cursor , массив столбцов для отображения ( adapterCols ) и массив представлений, с помощью которых должны отображаться столбцы ( adapterRowViews ). Затем устанавливаем Spinner Adapter для SimpleCursorAdapter :

String[] queryCols = new String[]; SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); Cursor cursor = database.query( SampleDBContract.Employer.TABLE_NAME, // Запрашиваемая таблица queryCols, // Возвращаемый столбец null, // Столбец для условия WHERE null, // Значение для условия WHERE null, // не группировать строки null, // не фильтровать по группам строк null // не сортировать ); String[] adapterCols = new String[]; int[] adapterRowViews = new int[]; SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter( this, android.R.layout.simple_spinner_item, cursor, adapterCols, adapterRowViews, 0); cursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); binding.employerSpinner.setAdapter(cursorAdapter);

Отображение данных из запроса SQLite в Spinner

Вставка внешнего ключа в базу данных

Вставка строки, содержащей внешний ключ, полностью идентична вставке строк в таблицу без ограничений по внешнему ключу. Разница заключается в том, что в Android SQLite примере мы получаем ссылку на выбранный объект Cursor из Spinner , а затем — значение столбца _ID Employer :

values.put(SampleDBContract.Employee.COLUMN_EMPLOYER_ID, ((Cursor)binding.employerSpinner.getSelectedItem()).getInt(0));

Вставка внешнего ключа в базу данных

Выборка данных из базы SQLite с помощью JOIN

Нельзя использовать метод SQLiteDatabase query() для выполнения запроса к нескольким таблицам. Для этого нужно составить собственный SQL-запрос . В приведенном ниже примере запрос определяется в классе SampleDBContract :

public static final String SELECT_EMPLOYEE_WITH_EMPLOYER = "SELECT * " + "FROM " + Employee.TABLE_NAME + " ee INNER JOIN " + Employer.TABLE_NAME + " er " + "ON ee." + Employee.COLUMN_EMPLOYER_ID + " = er." + Employer._ID + " WHERE " + "ee." + Employee.COLUMN_FIRSTNAME + " like ? AND ee." + Employee.COLUMN_LASTNAME + " like ?";

Обратите внимание, что в условии WHERE мы используем символ « ? ». Чтобы не нарушить синтаксис SQL нужно определить selectArgs String [] со значениями, которые будут заменять в предоставленном SQL-запросе символ « ? »:

private void readFromDB() < String firstname = binding.firstnameEditText.getText().toString(); String lastname = binding.lastnameEditText.getText().toString(); SQLiteDatabase database = new SampleDBSQLiteHelper(this).getReadableDatabase(); String[] selectionArgs = ; Log.d(TAG, SampleDBContract.Employee.QUERY_WITH_EMPLOYER); Cursor cursor = database.rawQuery(SampleDBContract.Employee.QUERY_WITH_EMPLOYER, selectionArgs); Log.d(TAG, "The total cursor count is " + cursor.getCount()); binding.recycleView.setAdapter(new SampleJoinRecyclerViewCursorAdapter(this, cursor)); >

Выборка данных из базы SQLite с помощью JOIN

В заключении

Полная версия исходного кода доступна на github для использования и изменения. Базы данных Android SQLite — это мощное средство, доступное для всех мобильных приложений.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *