SnappyDB — NoSQL key-value база данных для Android. Она довольно проста в использовании и является неплохим вариантом, если вы хотите использовать NoSQL вариант базы данных в своём проекте (подробнее тут).
По заявлениям разработчиков, в операциях записи и чтения Snappy превосходит по скорости SQLite:
Итак, начнём. Для начала необходимо добавить dependencies в build.gradle:
Теперь начнём, непосредственно, работу с самой БД.
Для начала разберёмся, как при помощи SnappyDB работать с примитивными типами и массивами, сохранять и получать их.
Для наглядности создадим небольшую разметку:
Допустим, что мы будем хранить в нашей БД данные о фильме
В MainActivity создадим метод PutValues:
Заметьте, что метод, в котором мы работаем со SnappyDB должен выбрасывать исключение SnappydbException.
Теперь напишем метод setValues для получения данных из БД и их вывода:
Вызовем созданные методы в onCreate (обязательно окружив их блоком try/catch):
Запускаем и видим, что всё работает исправно:
А теперь разберёмся, как работать с собственными классами и другими сложными типами.
Создадим класс Film с 3 полями:
Уберём вызовы методов setValues и putValues в onCreate. Создадим в нём новый объект класса Film и добавим его в БД:
Переработаем метод setValues:
Вновь вызовем setValues в onCreate:
Запускаем и видим, что всё работает:
Теперь давайте рассмотрим ещё несколько интересных функций SnappyDB:
1) Возможность искать ключи по префиксу:
Вывод в лог
2) Итерация по БД:
Без использования byBatch у вас будет только KeyIterator, который не реализует Iterator или Iterable, поэтому вы не можете использовать его в цикле.
byBatch (n) создает BatchIterable, который является Iterable и Iterator. По сути, он просто вызывает next (n) для KeyIterator, когда вы вызываете next () для него.
Но byBatch стоит использовать только при большом кол-ве данных. В ином случае стоит использовать findKeys/findKeysBetween.
3) Удаление элемента по ключу:
Элемент удалён
4) Закрытие и удаление БД:
5) Узнать, существует ли ключ в БД:
Ну вот и всё. Вам решать, использовать ли эту БД в своих проектах. Она достаточно быстра и проста в использовании, но выбор за вами. Это далеко не единственная БД для Android. Возможно, для вашего проекта лучше подойдёт другая БД (Room, SQLite, Realm и т.д). Вариантов масса.
P.S: SnappyDB на GitHub (оф.документация там же).
Различия между SQL и NoSQL: 1, 2
SQL vs Key-Value DB
По заявлениям разработчиков, в операциях записи и чтения Snappy превосходит по скорости SQLite:
Итак, начнём. Для начала необходимо добавить dependencies в build.gradle:
implementation 'com.snappydb:snappydb-lib:0.5.2'
implementation 'com.esotericsoftware.kryo:kryo:2.24.0'
Теперь начнём, непосредственно, работу с самой БД.
Для начала разберёмся, как при помощи SnappyDB работать с примитивными типами и массивами, сохранять и получать их.
Для наглядности создадим небольшую разметку:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/filmNameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:layout_centerInParent="true"
android:layout_margin="8dp"
/>
<TextView
android:id="@+id/filmBudgetTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="25sp"
android:layout_below="@+id/filmNameTextView"
android:layout_margin="8dp"
/>
<TextView
android:id="@+id/genreTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="25sp"
android:layout_below="@id/filmBudgetTextView"
android:layout_margin="8dp"
/>
<TextView
android:id="@+id/isAdult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/genreTextView"
android:textSize="25sp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Допустим, что мы будем хранить в нашей БД данные о фильме
В MainActivity создадим метод PutValues:
private void putValues(String name, int budget, boolean isAdult, String[] genres) throws SnappydbException {
DB snappyDB = DBFactory.open(this,"Film");
// создание БД с именем Film (для создания новой также используется метод open)
snappyDB.put("Name", name);
snappyDB.putInt("budget", budget);
snappyDB.putBoolean("isAdult", isAdult);
snappyDB.put("genres", genres);
//кладём в БД данные в зависимости от типа
}
Заметьте, что метод, в котором мы работаем со SnappyDB должен выбрасывать исключение SnappydbException.
Теперь напишем метод setValues для получения данных из БД и их вывода:
private void setValues(DB snappyDB) throws SnappydbException {
TextView filmNameTextView = findViewById(R.id.filmNameTextView),
filmBudgetTextView = findViewById(R.id.filmBudgetTextView),
genresTextView = findViewById(R.id.genreTextView),
isAdultTextView = findViewById(R.id.isAdult); //поля из созданной ранее разметки
String name = snappyDB.get("Name");
int budget = snappyDB.getInt("budget");
boolean isAdult = snappyDB.getBoolean("isAdult");
String[] genres = snappyDB.getObjectArray("genres", String.class);//2 параметр = имя класса
// метод get... в зависимости от типа данных
filmNameTextView.setText(name);
filmBudgetTextView.setText(String.valueOf(budget));
isAdultTextView.setText(String.valueOf(isAdult));
for(int i = 0;i < genres.length;i++) {
genresTextView.setText(genresTextView.getText() + " " + genres[i]);
}
}
Вызовем созданные методы в onCreate (обязательно окружив их блоком try/catch):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
putValues("Forrest Gump", 677000000,false, new String[] {"Drama","Melodrama"});
} catch (SnappydbException e) {
e.printStackTrace();
}
try {
DB snappyDB = DBFactory.open(this, "Film");
setValues(snappyDB);
} catch (SnappydbException e) {
e.printStackTrace();
}
}
Запускаем и видим, что всё работает исправно:
А теперь разберёмся, как работать с собственными классами и другими сложными типами.
Создадим класс Film с 3 полями:
public class Film {
private String name;
private int budget;
private String[] genres;
public Film() {}
public Film(String name, int budget, String[] genres) {
this.name = name;
this.budget = budget;
this.genres = genres;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getBudget() {
return budget;
}
public void setBudget(int budget) {
this.budget = budget;
}
public String[] getGenres() {
return genres;
}
public void setGenres(String[] genres) {
this.genres = genres;
}
}
Уберём вызовы методов setValues и putValues в onCreate. Создадим в нём новый объект класса Film и добавим его в БД:
Film film = new Film("Shawshank redemption",28000000, new String[] {"Drama"});
try {
DB snappyDB = DBFactory.open(this, "NewFilmDB");
snappyDB.put("FilmObj",film);
} catch (SnappydbException e) {
e.printStackTrace();
}
Переработаем метод setValues:
private void setValues(DB snappyDB) throws SnappydbException {
TextView filmNameTextView = findViewById(R.id.filmNameTextView),
filmBudgetTextView = findViewById(R.id.filmBudgetTextView),
genresTextView = findViewById(R.id.genreTextView);
Film film = snappyDB.getObject("FilmObj", Film.class);
String name = film.getName();
int budget = film.getBudget();
String[] genres = film.getGenres();
filmNameTextView.setText(name);
filmBudgetTextView.setText(String.valueOf(budget));
for(int i = 0;i < genres.length;i++) {
genresTextView.setText(genresTextView.getText() + " " + genres[i]);
}
}
Вновь вызовем setValues в onCreate:
try {
DB snappyDB = DBFactory.open(this, "NewFilmDB");
setValues(snappyDB);
} catch (SnappydbException e) {
e.printStackTrace();
}
Запускаем и видим, что всё работает:
Теперь давайте рассмотрим ещё несколько интересных функций SnappyDB:
1) Возможность искать ключи по префиксу:
Film film1 = new Film("Green mile",60000000,new String[] {"Drama", "Fantasy"}),
film2 = new Film("Gentlemen",22000000,new String[] {"Comedy", "Crime"}),
film3 = new Film("In Bruges",15000000,new String[] {"Comedy", "Crime", "Thriller"});
try {
DB snappyDB = DBFactory.open(this, "NewFilmDB");
snappyDB.put("FilmObj: Green Mile",film1);
snappyDB.put("FilmObj: Gentlemen",film2);
snappyDB.put("FilmObj: In Bruges",film3);
String[] filmKeys = snappyDB.findKeys("FilmObj:");
//помещаем в массив filmKeys ключи с префиксом "FilmObj:"
//если по одному ключу помещаются несколько значений, рассматривается последний добавленный
for(int i = 0;i < filmKeys.length;i++) {
Log.d("film_key: ", filmKeys[i] + "\n");
}
Log.d("film_name: ", snappyDB.getObject(filmKeys[2],Film.class).getName() + "\n");
//выводим эл-т по ключу, взятому из массива filmKeys
} catch (SnappydbException e) {
e.printStackTrace();
}
Вывод в лог
2) Итерация по БД:
try {
DB snappyDB = DBFactory.open(this, "NewFilmDB");
for (String[] batch : snappyDB.allKeysIterator().byBatch(1)) {
//итераторы работают с пакетами ключей(batch), а не с самими ключами
for (String key : batch) {
Log.d("film",snappyDB.getObject(key,Film.class).getName());
}
}
} catch (SnappydbException e) {
e.printStackTrace();
}
Без использования byBatch у вас будет только KeyIterator, который не реализует Iterator или Iterable, поэтому вы не можете использовать его в цикле.
byBatch (n) создает BatchIterable, который является Iterable и Iterator. По сути, он просто вызывает next (n) для KeyIterator, когда вы вызываете next () для него.
Но byBatch стоит использовать только при большом кол-ве данных. В ином случае стоит использовать findKeys/findKeysBetween.
3) Удаление элемента по ключу:
snappyDB.del("FilmObj: Gentlemen");
Элемент удалён
4) Закрытие и удаление БД:
snappyDB.close();
snappyDB.destroy();
5) Узнать, существует ли ключ в БД:
snappyDB.put("FilmObj: Gentlemen",new Film());
boolean isExist = snappyDB.exists("FilmObj: Gentlemen");// true
snappyDB.del("FilmObj: Gentlemen");
isExist = snappyDB.exists("FilmObj: Gentlemen");//false
Ну вот и всё. Вам решать, использовать ли эту БД в своих проектах. Она достаточно быстра и проста в использовании, но выбор за вами. Это далеко не единственная БД для Android. Возможно, для вашего проекта лучше подойдёт другая БД (Room, SQLite, Realm и т.д). Вариантов масса.
P.S: SnappyDB на GitHub (оф.документация там же).
Различия между SQL и NoSQL: 1, 2
SQL vs Key-Value DB