A EVOLUÇÃO DA
PERSISTÊNCIA DE
DADOS (COM SQLITE)
NO ANDROID
http://bit.ly/evolucao-persistencia
RODRIGO CASTRO
Desenvolvedor Android @ Concrete
Analista de Sistemas pela UFMS/CPCX.
De Coxim/MS para o mundo!
http://castrors.github.io
rodrigo.castro@concrete.com.br
@rodrigocastro_o
SUMÁRIO
Conteúdo
• SQLiteOpenHelper
• Libs de terceiros
• Room API
SQLITE OPEN HELPER
https://developer.android.com/training/basics/data-st
orage/databases.html
SETUP
public class LoanDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
static final String DATABASE_NAME = "openhelper.db";
private static final String TAG = "LoanDbHelper";
private LoanDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
ON CREATE E ON UPGRADE
@Override
public void onCreate(SQLiteDatabase db) {
final String SQL_CREATE_BOOK_TABLE = "CREATE TABLE " +
BookEntry.TABLE_NAME + " (" +
BookEntry._ID + " INTEGER PRIMARY KEY," +
BookEntry.COLUMN_TITLE + " TEXT NOT NULL);";
db.execSQL(SQL_CREATE_BOOK_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + BookEntry.TABLE_NAME);
onCreate(db);
}
}
INSERT
public void addBook(Book book) {
SQLiteDatabase db = getWritableDatabase();
db.beginTransaction();
try {
ContentValues values = new ContentValues();
values.put(BookEntry._ID, book.getId());
values.put(BookEntry.COLUMN_TITLE, book.getTitle());
db.insertOrThrow(BookEntry.TABLE_NAME, null, values);
db.setTransactionSuccessful();
} catch (Exception e) {
Log.d(TAG, "Error while trying to add book to database");
} finally {
db.endTransaction();
}
}
SELECT
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM book", null);
try {
if (cursor.moveToFirst()) {
do {
int bookId = cursor.getInt(cursor.getColumnIndex(BookEntry._ID));
String title = cursor.getString(cursor.getColumnIndex(BookEntry.COLUMN_TITLE));
Book book = new Book(bookId, title);
books.add(book);
} while (cursor.moveToNext());
}
} catch (Exception e) {
Log.d(TAG, "Error while trying to get books from database");
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
BIBLIOTECAS ORM DE
TERCEIROS
https://android-arsenal.com/tag/69?sort=created
https://www.sitepoint.com/5-best-android-orms/
ORMLITE
@DatabaseTable(tableName = "user")
public class User {
@DatabaseField(id = true)
private String username;
@DatabaseField
private String password;
public User() {
// ORMLite needs a no-arg constructor
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
// Implementing getter and setter methods
}
SURGAR ORM
public class User extends SugarRecord<User> {
String username;
String password;
int age;
@Ignore
String bio; //this will be ignored by SugarORM
public User() { }
public User(String username, String password,int age){
this.username = username;
this.password = password;
this.age = age;
}
}
ACTIVE ANDROID
@Table(name = "User")
public class User extends Model {
@Column(name = "username")
public String username;
@Column(name = "password")
public String password;
public User() {
super();
}
public User(String username,String password) {
super();
this.username = username;
this.password = password;
}
}
GREEN DAO
@Entity(indexes = {
@Index(value = "username DESC", unique = true)
})
public class User {
@Id
private Long id;
@NotNull
private String username;
private String password;
//getters and setters
}
ANDROID DEV SUMMIT 2015 (44:02 - 44:53)
TÍTULO
SLIDES
GOOGLE I/O 2017 (2:26 - 2:35)
ROOM API
https://developer.android.com/topic/libraries/architec
ture/room.html
SETUP
compile 'android.arch.persistence.room:runtime:1.0.0-alpha3'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha3'
ENTITY
@Entity
public class User {
@PrimaryKey
String id;
String name;
String lastName;
int age;
}
DATABASE
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase instance;
public abstract UserDao userModel();
public static AppDatabase getDatabase(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
}
return instance;
}
public static void destroyInstance() {
instance = null;
}
}
DAO
@Dao
public interface UserDao {
@Query("select * from user")
List<User> loadAllUsers();
@Query("select * from user where id = :id")
User loadUserById(int id);
@Query("select * from user where name = :firstName and lastName = :lastName")
List<User> findByNameAndLastName(String firstName, String lastName);
}
DAO
@Dao
public interface UserDao {
@Insert(onConflict = IGNORE)
void insertOrReplaceUsers(User... users);
@Delete
void deleteUsers(User user1, User user2);
}
DAO
@Dao
public interface UserDao {
@Query("select name from user")
List<String> loadAllUserNames();
@Query("select age, name from user")
List<Pojo> loadAllUsersWithAgeAndName();
class Pojo {
int age;
String name;
}
}
ERRORS
SQLiteOpenHelper - Runtime Exception
Caused by: android.database.sqlite.SQLiteException: no such table: users
(code 1): , while compiling: SELECT * FROM users
Room API - Compile Error
Error:(31, 18) error: There is a problem with the query: [SQLITE_ERROR]
SQL error or missing database (no such table: users)
TYPE CONVERTER
public class DateConverter {
@TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
@TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
@TypeConverters(DateConverter.class)
EMBEDDED
@Entity
public class User {
@PrimaryKey
String id;
String name;
String lastName;
int age;
Location location;
}
Error:(29, 21) error: Cannot figure out how to save this field into database.
You can consider adding a type converter for it.
EMBEDDED
@Entity
public class User {
@PrimaryKey
String id;
String name;
String lastName;
int age;
@Embedded
Location location;
}
SMART JOIN
@Query("SELECT Loan.id, Book.title, User.name, Loan.startTime, Loan.endTime From Loan " +
"INNER JOIN Book ON Loan.book_id = Book.id " +
"INNER JOIN User ON Loan.user_id = User.id ")
List<LoanWithUserAndBook> findAllWithUserAndBook();
@Query("SELECT startTime, name From Loan, User " +
"WHERE Loan.user_id = User.id ")
List<StartTimeWithUsername> findLoanStartTimeWithUsername();
class StartTimeWithUsername {
Date startTime;
String name;
}
MAIS ALGUMAS FEATURES
INDEX
MIGRATIONS
TESTABILITY
LINKS INTERESSANTES
https://github.com/castrors/PersistenceTalk
https://developer.android.com/topic/libraries/architecture/index.html
https://codelabs.developers.google.com/codelabs/android-persistence/index.html
https://codelabs.developers.google.com/codelabs/android-lifecycles/index.html
https://www.youtube.com/watch?v=MfHsPGQ6bgE
https://www.youtube.com/watch?v=FrteWKKVyzI
OBRIGADO!
Centro
Av. Presidente Wilson,
231 - 29º andar
(21) 2240-2030
Cidade Monções
Av. Nações Unidas,
11.541 - 3º andar
(11) 4119-0449
Savassi
Av. Getúlio Vargas, 671
Sala 800 - 8º andar
(31) 3360-8900
www.concrete.com.br

A evolução da persistência de dados (com sqlite) no android