The template I use for SQLite database interaction is the following:
The helper for creating database:
public class DatabaseHelper extends SQLiteOpenHelper
{
private static final String DATABASE_NAME = "database.db";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database)
{
Table1.onCreate(database);
Table2.onCreate(database);
Table3.onCreate(database);
}
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
Table1.onUpgrade(database, oldVersion, newVersion);
Table2.onUpgrade(database, oldVersion, newVersion);
Table3.onUpgrade(database, oldVersion, newVersion);
}
}
A table as an example:
public class Table1
{
public static final String TABLE_TABLE1 = "table1";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_PHONENUMBER = "phoneNumber";
public static final String COLUMN_EMAIL = "email";
private static final String DATABASE_CREATE = "create table " + TABLE_TABLE1 + "("
+ COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_NAME + " text not null, "
+ COLUMN_PHONENUMBER + " text not null, "
+ COLUMN_EMAIL + " text not null, "
+ ");";
public static void onCreate(SQLiteDatabase database)
{
database.execSQL(DATABASE_CREATE);
}
public static void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
Log.w(Table1.class.getName(), "Upgrading from version " + oldVersion + " to " + newVersion);
database.execSQL("DROP TABLE IF EXISTS " + TABLE_TABLE1);
onCreate(database);
}
}
Operations for table:
public class Table1DataSource
{
// Database fields
private SQLiteDatabase database;
private DatabaseHelper dbHelper;
private String[] allColumns = { Table1.COLUMN_ID, Table1.COLUMN_NAME,
Table1.COLUMN_PHONENUMBER, Table1.COLUMN_EMAIL };
public Table1DataSource(Context context)
{
dbHelper = new DatabaseHelper(context);
}
public void open() throws SQLException
{
database = dbHelper.getWritableDatabase();
}
public void close()
{
dbHelper.close();
}
private EmployeeDB cursorToEmployee(Cursor cursor)
{
EmployeeDB Employee = new EmployeeDB();
Employee.setId(cursor.getLong(0));
Employee.setName(cursor.getString(1));
Employee.setPhoneNumber(cursor.getString(2));
Employee.setEmail(cursor.getString(3));
return Employee;
}
public EmployeeDB createEmployee(String name, String phoneNumber, String email)
{
ContentValues values = new ContentValues();new
values.put(Table1.COLUMN_NAME, name);
values.put(Table1.COLUMN_PHONENUMBER, phoneNumber);
values.put(Table1.COLUMN_EMAIL, email);
long insertId = database.insert(Table1.TABLE_TABLE1, null, values);
Cursor cursor = database.query(Table1.TABLE_TABLE1, allColumns, Table1.COLUMN_ID
+ " = " + insertId, null, null, null, null);
cursor.moveToFirst();
EmployeeDB newEmployee = cursorToEmployee(cursor);
cursor.close();
return newEmployee;
}
public void updateEmployee(EmployeeDB employee)
{
ContentValues values = new ContentValues();
values.put(Table1.COLUMN_NAME, name);
values.put(Table1.COLUMN_PHONENUMBER, phoneNumber);
values.put(Table1.COLUMN_EMAIL, email);
database.update(Table1.TABLE_TABLE1, values, Table1.COLUMN_ID + " = ?", new String[]{""+employee.getId()});
}
public void deleteEmployee(EmployeeDB Employee)
{
long id = Employee.getId();
database.delete(EmployeeTable.TABLE_EMPLOYEE, EmployeeTable.COLUMN_ID + " = " + id, null);
}
public Cursor getAllEmployees()
{
return database.query(EmployeeTable.TABLE_EMPLOYEE, allColumns, null, null, null, null, null);
}
public EmployeeDB findEmployeeById(long id)
{
EmployeeDB employee = null;
Cursor cursor = database.query(EmployeeTable.TABLE_EMPLOYEE, allColumns, EmployeeTable.COLUMN_ID + " = ?", new String[] {""+id}, null, null, null);
if(cursor.moveToFirst())
{
employee = cursorToEmployee(cursor);
}
return employee;
}
public List<EmployeeDB> getAllEmployeesList()
{
List<EmployeeDB> Employees = new ArrayList<EmployeeDB>();
Cursor cursor = getAllEmployees();
if (cursor.moveToFirst())
{
do
{
EmployeeDB Employee = cursorToEmployee(cursor);
Employees.add(Employee);
}
while (cursor.moveToNext());
}
cursor.close();
return Employees;
}
}
EDIT: Slightly more updated version (revisited in 2017-04-29):
public class DatabaseManager
extends SQLiteOpenHelper {
public interface Table {
String getTableName();
Fields[] getFields();
void onCreate(SQLiteDatabase database);
void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion);
}
public interface Fields {
String getFieldName();
String getFieldType();
String getFieldAdditional();
}
public interface QueryDefinition {
Cursor query(SQLiteDatabase database, Table table, String[] allFields);
}
private static final String DATABASE_NAME = "database.db";
private static final int DATABASE_VERSION = 1;
private final List<Table> tables;
private SQLiteDatabase database;
public DatabaseManager(Context appContext, List<Table> tables) {
super(appContext, DATABASE_NAME, null, DATABASE_VERSION);
this.tables = tables;
this.database = getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase database) {
for(Table table : tables) {
table.onCreate(database);
}
}
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
for(Table table : tables) {
table.onUpgrade(database, oldVersion, newVersion);
}
}
public interface Transaction {
void execute(SQLiteDatabase sqLiteDatabase);
}
public interface Mapper<T> {
T from(Cursor cursor);
ContentValues from(ContentValues contentValues, T t);
}
public void executeTransaction(Transaction transaction) {
try {
database.beginTransaction();
transaction.execute(database);
database.setTransactionSuccessful();
} finally {
if(database.inTransaction()) {
database.endTransaction();
}
}
}
public <T> List<T> findAll(Table table, Mapper<T> mapper) {
return findAll(table,
mapper, (database, _table, allFields) -> database.query(_table.getTableName(), allFields, null, null, null, null, null));
}
public <T> List<T> findAll(Table table, Mapper<T> mapper, QueryDefinition queryDefinition) {
String[] allFields = extractFieldsFromTable(table);
Cursor cursor = queryDefinition.query(database, table, allFields);
List<T> list = collectObjectFromCursor(mapper, cursor);
cursor.close();
return list;
}
private <T> List<T> collectObjectFromCursor(Mapper<T> mapper, Cursor cursor) {
List<T> list = new LinkedList<>();
if(cursor.moveToFirst()) {
do {
T object = mapper.from(cursor);
list.add(object);
} while(cursor.moveToNext());
}
return new ArrayList<>(list);
}
@NonNull
private String[] extractFieldsFromTable(Table table) {
Fields[] _fields = table.getFields();
String[] fields = new String[_fields.length];
int i = 0;
for(Fields field : _fields) {
fields[i++] = field.getFieldName();
}
return fields;
}
}
public abstract class BaseTable
implements DatabaseManager.Table {
@Override
public void onCreate(SQLiteDatabase database) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("CREATE TABLE ");
stringBuilder.append(getTableName());
stringBuilder.append("(");
DatabaseManager.Fields[] fields = getFields();
int size = fields.length;
int i = 0;
for(DatabaseManager.Fields field : fields) {
stringBuilder.append(field.getFieldName());
stringBuilder.append(" ");
stringBuilder.append(field.getFieldType());
stringBuilder.append(" ");
if(field.getFieldAdditional() != null) {
stringBuilder.append(field.getFieldAdditional());
}
if(i < size - 1) {
stringBuilder.append(",");
}
i++;
}
stringBuilder.append(");");
database.execSQL(stringBuilder.toString());
}
@Override // TODO: implement migration
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
Log.w("Table[" + getTableName() + "]", "Upgrading from version " + oldVersion + " to " + newVersion);
database.execSQL("DROP TABLE IF EXISTS " + getTableName());
onCreate(database);
}
}
public enum Tables {
CAT(new CatTable());
private DatabaseManager.Table table;
Tables(DatabaseManager.Table table) {
this.table = table;
}
public <T extends DatabaseManager.Table> T getTable() {
//noinspection unchecked
return (T) table;
}
public static List<DatabaseManager.Table> getTables() {
Tables[] _tables = Tables.values();
List<DatabaseManager.Table> tables = new ArrayList<>(_tables.length);
for(Tables table : _tables) {
tables.add(table.table);
}
return tables;
}
}
public class CatTable
extends BaseTable {
public static final String NAME = "cat";
public enum Fields
implements DatabaseManager.Fields {
ID("_id", "text", "primary key"), //"integer", "primary key autoincrement"),
URL("url", "text", "not null"),
SOURCE_URL("sourceUrl", "text", "not null");
private String fieldName;
private String fieldType;
private String fieldAdditional;
Fields(String fieldName, String fieldType, String fieldAdditional) {
this.fieldName = fieldName;
this.fieldType = fieldType;
this.fieldAdditional = fieldAdditional;
}
public String getFieldName() {
return fieldName;
}
public String getFieldType() {
return fieldType;
}
public String getFieldAdditional() {
return fieldAdditional;
}
}
@Override
public String getTableName() {
return NAME;
}
@Override
public DatabaseManager.Fields[] getFields() {
return Fields.values();
}
}
public class CatMapper
implements DatabaseManager.Mapper<Cat> {
@Override
public Cat from(Cursor cursor) {
return Cat.create(cursor.getString(0), cursor.getString(1), cursor.getString(2));
}
@Override
public ContentValues from(ContentValues contentValues, Cat cat) {
contentValues.put(CatTable.Fields.ID.getFieldName(), cat.id());
contentValues.put(CatTable.Fields.URL.getFieldName(), cat.url());
contentValues.put(CatTable.Fields.SOURCE_URL.getFieldName(), cat.sourceUrl());
}
}
public class CatDao {
CatTable catTable;
CatMapper catMapper;
DatabaseManager databaseManager;
public CatDao(CatTable catTable, CatMapper catMapper, DatabaseManager databaseManager) {
this.catTable = catTable;
this.catMapper = catMapper;
this.databaseManager = databaseManager;
}
public List<Cat> findAll() {
return databaseManager.findAll(catTable, catMapper);
}
public void insert(List<Cat> cats) {
databaseManager.executeTransaction(sqLiteDatabase -> {
ContentValues contentValues = new ContentValues();
for(Cat cat : cats) {
contentValues = mapper.from(contentValues, cat);
sqLiteDatabase.insertWithOnConflict(catTable.getTableName(), null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);
}
});
}
}
@AutoValue
public abstract class Cat {
public abstract String id();
public abstract String url();
public abstract String sourceUrl();
public static Cat create(String id, String url, String sourceUrl) {
return new AutoValue_Cat.Builder().setId(id).setUrl(url).setSourceUrl(sourceUrl).build();
}
public Builder toBuilder() {
return new AutoValue_Cat.Builder(this);
}
@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setId(String id);
public abstract Builder setUrl(String url);
public abstract Builder setSourceUrl(String sourceUrl);
public abstract Cat build();
}
}