Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Simplifiez vous la base avec SQLDelight et SQLBrite

julienbanse
September 20, 2017

Simplifiez vous la base avec SQLDelight et SQLBrite

comment SQLDelight apporte une représentation objet de vos tables et requetes SQL en utilisant directement le sql.
Quand à SQLBrite, il apporte l'implémentation réactive au SQL.
Lien de la conf : https://www.youtube.com/watch?v=p-nsG7V__pY&index=3&list=PLv7xGPH0RMURKgO-DmW6TZniWysGwnbmU
Projet sample : https://github.com/julienbanse/DemoSQL

julienbanse

September 20, 2017
Tweet

Other Decks in Programming

Transcript

  1. ANDROID ET SQLITE DÉFINIR UNE TABLE public final class FeedReaderContract

    { public static class FeedEntry implements BaseColumns { public static final String TABLE_NAME = "entry"; public static final String COLUMN_NAME_TITLE = "title"; public static final String COLUMN_NAME_SUBTITLE = "subtitle"; } private static final String SQL_CREATE_ENTRIES = "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + FeedEntry._ID + " INTEGER PRIMARY KEY," + FeedEntry.COLUMN_NAME_TITLE + " TEXT," + FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)"; private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME; } https://developer.android.com/training/basics/data-storage/databases.html
  2. ANDROID ET SQLITE INSÉRER private void insert(String title, String subtitle)

    { SQLiteDatabase db = mDbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, title); values.put(FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE, subtitle); long newRowId = db.insert(FeedReaderContract.FeedEntry.TABLE_NAME, null, values); } https://developer.android.com/training/basics/data-storage/databases.html
  3. ANDROID ET SQLITE SÉLECTIONNER private Cursor select() { SQLiteDatabase db

    = mDbHelper.getReadableDatabase(); String[] projection = { FeedReaderContract.FeedEntry._ID, FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE, FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE }; String selection = FeedReaderContract.FeedEntry.COLUMN_NAME_TITLE + " = ?"; String[] selectionArgs = {"My Title"}; String sortOrder = FeedReaderContract.FeedEntry.COLUMN_NAME_SUBTITLE + " DESC"; Cursor cursor = db.query( FeedReaderContract.FeedEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder ); return cursor; }
  4. ANDROID ET SQLITE LIRE LE RÉSULTAT private void readCursor(Cursor cursor){

    List itemIds = new ArrayList<>(); while (cursor.moveToNext()) { long itemId = cursor.getLong( cursor.getColumnIndexOrThrow(FeedReaderContract.FeedEntry._ID)); itemIds.add(itemId); } cursor.close(); } https://developer.android.com/training/basics/data-storage/databases.html
  5. ANDROID ET SQLITE UTILISER LA BASE DE DONNÉES ▸ SQLiteOpenHelper

    ▸ ContentValues ▸ Cursor ▸ CursorLoader ▸ … ▸ et beaucoup de définitions https://developer.android.com/training/basics/data-storage/databases.html
  6. DES LIBRAIRIES BEAUCOUP DE SOLUTIONS EXISTANTES ▸ Green DAO ▸

    OrmLite ▸ Requery ▸ Freezer ▸ DBFLow ▸ ….
  7. DES LIBRAIRIES POUR QUEL BESOIN ? ▸ Encapsulation du sql

    ▸ Définition du modèle en partant d’objet ▸ De meilleures performances ? ▸ Et les fonctions SQLite ?
  8. SQLDELIGHT ▸ Plugin IntelliJ ▸ Plugin Gradle ▸ Génération de

    classes modèles associées aux tables de la base de données ▸ Typage des champs ▸ v0.6.1
  9. SQLDELIGHT SQL FIRST ▸ Ecrire du SQL CREATE TABLE IF

    NOT EXISTS news( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, title TEXT ); ▸ Génère du JAVA ▸ Interface modèle par table et select SQL ▸ Wrapper autour du Cursor ▸ Factory pour créer les select SQL
  10. SQLDELIGHT MODÈLE public interface NewsModel { String TABLE_NAME = "news";

    String ID = "id"; String TITLE = "title"; String CREATE_TABLE = "" + "CREATE TABLE IF NOT EXISTS news(\n" + " id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,\n" + " title TEXT\n" + ")"; long id(); @Nullable String title(); }
  11. SQLDELIGHT SELECT ▸ SQL selectMostRecent: SELECT * FROM news; final

    class Factory<T extends NewsModel> { public final Creator<T> creator; public Factory(Creator<T> creator) { this.creator = creator; } public SqlDelightStatement selectMostRecent() { return new SqlDelightStatement("" + "SELECT * FROM news", new String[0], Collections.<String>singleton("news")); } public Mapper<T> selectMostRecentMapper() { return new Mapper<T>(this); } } ▸ Java
  12. SQLDELIGHT INSERT / UPDATE / DELETE ▸ Java final class

    InsertItem extends SqlDelightCompiledStatement.Insert { public InsertItem(SQLiteDatabase database) { super("news", database.compileStatement("" + "INSERT INTO news(title) VALUES(?)")); } public void bind(@Nullable String title) { if (title == null) { program.bindNull(1); } else { program.bindString(1, title); } } } ▸ SQL insertItem: INSERT INTO news(title) VALUES(?);
  13. SQLDELIGHT ET LE MODÈLE ? ON EN FAIT QUOI ?

    @AutoValue abstract class News : NewsModel { companion object { val FACTORY: NewsModel.Factory<News> = NewsModel.Factory<News>(NewsModel.Creator<News>(::AutoValue_News)) } }
  14. SQLDELIGHT TYPE CUSTOM ▸ Type non géré par le moteur

    sql ? ▸ Enum, Boolean ▸ Autre ? ColumnAdapter class DateAdapter : ColumnAdapter<Date, Long> { override fun decode(databaseValue: Long?): Date { if (databaseValue == null) { return Date() } else { return Date(databaseValue) } } override fun encode(value: Date): Long { return value.time } }
  15. SQLDELIGHT CE QU’IL FAUT RETENIR ▸ Concevoir le modèle de

    données en SQL ▸ La modification des requêtes ou du modèle aura un impact direct sur le code ▸ Il faut gérer les update du modèle manuellement
  16. SQLBRITE ▸ Apporte l’implémentation réactive pour une base de données

    et/ou un content provider ▸ Wrapper autour de SQLiteOpenHelper ou ContentResolver ▸ RxJava 1 et 2 ▸ Ce n’est pas un ORM
  17. SQLBRITE ▸ Query SQL ▸ Transaction ▸ Notifications de changements

    ▸ Mapping des résultats (cursor -> objets)
  18. SQLBRITE WRAPPER BDD fun briteDatabase(sqLiteOpenHelper: SQLiteOpenHelper): BriteDatabase { val briteDb

    = SqlBrite.Builder() .logger { message -> Log.d("Database", message) } .build() .wrapDatabaseHelper(sqLiteOpenHelper, Schedulers.single()) briteDb.setLoggingEnabled(BuildConfig.DEBUG) return briteDb } ▸ Scheduler pour les notifications de changement
  19. TIPS AND LINKS ▸ Tester la montée de version de

    la base ▸ blog post par Jérémie Martinez : http://jeremie- martinez.com/2016/02/16/unit-tests/ ▸ Fan de Retrofit ? ▸ Insert/Update/Delete généré instantié en lazy ▸ Gérer les performances de son modèle ▸ https://medium.com/@JasonWyatt/squeezing-performance- from-sqlite-indexes-indexes-c4e175f3c346 fun Response<*>.isFromLocalCache(): Boolean { return raw().networkResponse() == null || (code() == HttpURLConnection.HTTP_NOT_MODIFIED) } EN VRAC
  20. TIPS AND LINKS LES OUTILS SQL ▸ Stetho (http://facebook.github.io/stetho/) ▸

    SQLScout (http://www.idescout.com/) ▸ Activer le strict mode en debug