0% ont trouvé ce document utile (0 vote)
16 vues94 pages

Bases de données et SGBD en Android

Le document présente les bases de données et les systèmes de gestion de bases de données (SGBD), en se concentrant sur les exigences, les transactions ACID et les opérations CRUD. Il aborde également les concepts de couches logicielles, le modèle de données, ainsi que des systèmes NoSQL et des bases de données orientées objet. Enfin, il met en avant SQLite comme un moteur de base de données relationnelle open source, adapté aux systèmes embarqués.

Transféré par

takwaafi7
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
16 vues94 pages

Bases de données et SGBD en Android

Le document présente les bases de données et les systèmes de gestion de bases de données (SGBD), en se concentrant sur les exigences, les transactions ACID et les opérations CRUD. Il aborde également les concepts de couches logicielles, le modèle de données, ainsi que des systèmes NoSQL et des bases de données orientées objet. Enfin, il met en avant SQLite comme un moteur de base de données relationnelle open source, adapté aux systèmes embarqués.

Transféré par

takwaafi7
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

IN01

Programmation Android
04 – Bases de données

Yann Caron

session sept 2014 Yann Caron (c) 2014 1


Sommaire - Séance 04
 Rappel sur les SGBD
 Couches logiciels
 SQLite
 Object Relational Mapping
 NoSQL - OODBMS - DB4Object

session sept 2014 Yann Caron (c) 2014 2


IN01 – Séance 04

Rappel sur les SGBD

session sept 2014 Yann Caron (c) 2014 3


Les bases de données

Wiki : une base de données est un magasin de
données composé de plusieurs fichiers manipulés
exclusivement par le SGBD

Ce dernier cache la complexité de manipulation
des structures de la base de données en mettant à
disposition une vue synthétique du contenu

Les SGBD sont les logiciels intermédiaires entre les
utilisateurs et les bases de données

session sept 2014 Yann Caron (c) 2014 4


Exigences d'un SGBD

Stocker des données, les modifier

Un processus d'interrogation et de recherche des
données selon un ou plusieurs critères

Pouvoir créer des sauvegardes et les restaurer si besoin

Application de règles pour assurer la cohérence des
données (selon les relations entre elles)

Sécurité : un processus d'authentification pour protéger
les données

session sept 2014 Yann Caron (c) 2014 5


Exigences d'un SGBD

Abstraire la couche de stockage et les
processus de requêtage

Logging : track les modifications effectuées
par les utilisateurs

Optimisation : performance tuning

session sept 2014 Yann Caron (c) 2014 6


ACID

Lors d'une manipulation des données, il faut toujours
s'assurer que la base de données conserve son intégrité

Une transaction (modification bornée) doit être :

Atomique : la suite des opérations est indivisible (synchronized)

Cohérente : le contenu FINAL doit être cohérent, même si les
étapes intermédiaires ne le sont pas

Isolée : pas d'interaction entre des transactions concurrentes

Durable : une fois validé, l'état devient permanent et aucun
incident technique ne doit altérer le résultat d'une transaction

session sept 2014 Yann Caron (c) 2014 7


CRUD

Opérations de base dans un SGBD

Create, Read, Update, Delete

Operation SQL HTTP DB4O


Create INSERT POST .store
Read SELECT GET .queryByExample
(Retrieve) .AsQueryable
Update UPDATE PUT / PATCH .store
Delete DELETE DELETE .delete

session sept 2014 Yann Caron (c) 2014 8


SGBDR

Système de gestion de bases de données
relationnelles

Relations :

One to one

One to many

Many to many

Normalisation

session sept 2014 Yann Caron (c) 2014 9


Bibliothèque
Book
title : nvarchar
isbn : nvarchar
nbPage : int

Book
title isbn nbPage
Croc blanc 2010034031 248
Vingt mille lieues sous les mers 353

session sept 2014 Yann Caron (c) 2014 10


Bibliothèque MCD

Customer n borrow n Book 1 belongs to n Genre

1
written by

Author

session sept 2014 Yann Caron (c) 2014 11


Bibliothèque MLD

Customer n 1 borrow 1 n Book 1 n Genre

1
fromDate toDate

Author

session sept 2014 Yann Caron (c) 2014 12


Queries

Tous les livres dont le nom commence par la
lettre “a”
➔ SELECT * FROM Book WHERE name LIKE 'A
%'

Tous les livres du même auteur
➔ SELECT * FROM Book b INNER JOIN Author
a ON b.idAuthor = a.id WHERE a.name =
'Jack London'

session sept 2014 Yann Caron (c) 2014 13


Ensembles

Sous-ensembles résultant de la jointure

A B
A B 1 NULL
1 3 2 NULL
FULL
2 4 = 3 3
JOIN
3 7 4 4
4 8 NULL 7
NULL 8

session sept 2014 Yann Caron (c) 2014 14


Ensembles

Inner Join Full Join


SELECT * FROM A SELECT * FROM A
INNER JOIN B FULL JOIN B
ON A.key = B.key ON A.key = B.key
A B A B
1 NULL 1 NULL
2 NULL 2 NULL
3 3 3 3
4 4 4 4
NULL 7 NULL 7
NULL 8 NULL 8

session sept 2014 Yann Caron (c) 2014 15


Ensembles

A B
1 NULL
2 NULL

Full Join 3 3
4 4
Sans intersection NULL 7
SELECT * FROM A
NULL 8
FULL JOIN B
ON A.key = B.key
WHERE A.key IS NULL
OR B.key IS NULL

session sept 2014 Yann Caron (c) 2014 16


Ensembles Left

Left Join
SELECT *
FROM A
LEFT JOIN B
Left Join A B
1 NULL
ON A.key = B.key sans intersection 2 NULL
A B SELECT *
3 3
1 NULL FROM A
4 4
2 NULL LEFT JOIN B
ON A.key = B.key NULL 7
3 3
WHERE B.key IS NULL NULL 8
4 4
NULL 7
NULL 8
session sept 2014 Yann Caron (c) 2014 17
Ensembles Right

Right Join
SELECT *
FROM A
RIGHT JOIN B
Right Join A B
1 NULL
ON A.key = B.key sans intersection 2 NULL
A B SELECT *
3 3
1 NULL FROM A
4 4
2 NULL RIGHT JOIN B
ON A.key = B.key NULL 7
3 3
WHERE A.key IS NULL NULL 8
4 4
NULL 7
NULL 8
session sept 2014 Yann Caron (c) 2014 18
Ensembles

Ne pas confondre avec le produit cartésien

Le résultat est l'ensemble de tous les couples
(distribution)
SELECT * FROM A CROSS JOIN B

session sept 2014 Yann Caron (c) 2014 19


CRUD - SQL98

Create :
➔ INSERT INTO Books (title, isbn, nbPage) VALUES
(“Croc blanc”, “2010034031”, 248)

Read :
➔ SELECT * FROM Books WHERE title = “Croc blanc”

Update :
➔ UPDATE Books SET nbPage = 248 WHERE title = “Croc
blanc”

Delete :
➔ DELETE FROM Books WHERE title = “Croc blanc”

session sept 2014 Yann Caron (c) 2014 20


IN01 – Séance 04

Couches logiciels

session sept 2014 Yann Caron (c) 2014 21


Patron - Layer

POSA : Pattern Oriented Software Architecture

Architecturer les applications en couches

Chaque couche a son niveau d'abstraction propre

Séparation des responsabilités par niveau
d'abstraction

Rend interchangeables les différentes couches

exemple : couches OSI (réseau)

session sept 2014 Yann Caron (c) 2014 22


Patron – Layer – Exemple
View Data Logger
Transfert
FishView FamilyView Objects

Fish Fish
Business Model

FishBO FamilyBO 1..1

Data Access Layer Familly

FishDAO (CRUD) FamilyDAO (CRUD)

FishDb4o FamilyDb4o

db4o

session sept 2014 Yann Caron (c) 2014 23


Patron - Layer

La couche L

Elle offre un service à la couche supérieure
(L+1)

Elle délègue les sous-tâches à la couche
inférieure (L–1)

Elle ne collabore qu'avec la couche
inférieure (L-1)

session sept 2014 Yann Caron (c) 2014 24


Patron - Layer

Communications descendantes directes
(création d'objets, appel de méthodes)

White boxe, les objets sont accessibles

Black boxe, les objets sont utilisés au travers d'un
adapter et/ou des interfaces

Communications ascendantes découplées
(callback, observer/observable, template method
– choix pour Algoid)

session sept 2014 Yann Caron (c) 2014 25


DTO – Data Transfert Object

Ensemble de POJO (Plain Old Java Object)
représente le modèle business

Pour chaque table de la DB = 1 POJO (bean)

Un bean mutable (attributs privés, getters,
setters, constructeur par défaut – state less,
constructeur avec assignation des attributs –
state full…)

session sept 2014 Yann Caron (c) 2014 26


Un design pattern : DAO

Data Access Object

Une interface CRUD : avec les méthodes de
création, lecture, modification et suppression

Permet une séparation des responsabilités
entre les objets métier et l'accès à la base de
données

1 table = 1 DAO = 1 DTO (bean)

session sept 2014 Yann Caron (c) 2014 27


Un design pattern : DAO

Objets métier DAO SGBD

POJO Tables
Data access abstraction

Factory

Interface DAO interface

DAO interface
create ()
selectAll ()
DAO select ()
update ()
delete ()

session sept 2014 Yann Caron (c) 2014 28


ORM

Object Relational Mapping

Un framework qui le fait pour nous

Transforme les objets en tables et vice versa, les attributs en champs.

Correspondance des types (Java/SQLite)

Plusieurs modes de configuration : XML, paramétrisation, annotations

Un grand nombre d'ORM sur le marché : Hibernate, OJB, SimpleORM,
ORMLite, Nhibernate, Entity Framework, Linq To SQL

Une problématique répandue

session sept 2014 Yann Caron (c) 2014 29


Autres possibilités

Systèmes NoSQL (Not Only SQL)

Document-oriented database system

Basé sur des standards de description de documents : XML, YAML,
JSON (JavaScript Object Notation), BSON (Binary JSON)

Informix, MongoDB, OrientDB, Cassandra

Graphs-oriented database system

OODBMS

Object oriented database management system

DB4O, une base de données embarquable sur Android

session sept 2014 Yann Caron (c) 2014 30


Différentes approches de la
persistance

session sept 2014 Yann Caron (c) 2014 31


SGBDOO - Avantages

Bénéficie de la puissance et de la flexibilité de
l'objet (avec les objets, on peut tout représenter)

Pas de mapping

Relation n/n (many to many) native

Héritage

Patron Composite

Découplage des complexités

session sept 2014 Yann Caron (c) 2014 32


Inconvénients

Limites des SGBDOO :

Méconnues

Manque de standardisation malgré l’ODMG (accès multiples)

Peu d'interopérabilité avec les BDR et les outils (OLAP, reporting)

Toutes n’implémentent pas encore le backup incrémental

Coût de migration élevé

Limitations peu importantes pour une DB embarquée sur
Android, n'est-ce pas ?

session sept 2014 Yann Caron (c) 2014 33


IN01 – Séance 04

SQLite

session sept 2014 Yann Caron (c) 2014 34


SQLite

Moteur de base de données relationnelle

Crée par D.Richard Hipp

Écrit en C (ANSI-C)

Open source sans restriction

Multiplate-forme

Le plus distribué au monde (Firefox, Skype, Google Gears)

Systèmes embarqués (iPhone, Symbian, Android, mais pas
sur Windows Phone)

session sept 2014 Yann Caron (c) 2014 35


SQLite

Implémente le standard SQL-92 (alias SQL2)

Et les propriétés ACID

SGBD embarqué

Pas de gestion des droits (mono-utilisateur)

Pas de configuration

session sept 2014 Yann Caron (c) 2014 36


Embarqué

Fichiers simples, Modèle embarqué, Modèle
client-serveur (n-tiers)
Espace application Espace application Espace application

Application Application Application

Données SQLite Client

Données SGBD

Données

session sept 2014 Yann Caron (c) 2014 37


Patron – Layer – Exemple
View Data Logger
Transfert
FishView FamilyView Objects

Fish
Business Model

FishBO FamilyBO 1..1

Data Access Layer Familly

FishDAO (CRUD) FamilyDAO (CRUD)

FishDb4o FamilyDb4o

db4o

session sept 2014 Yann Caron (c) 2014 38


Mais…

Dépendant du système de fichier

une base de données = un fichier

Attention à la limite sur des DD formatés en FAT 32

Pas d'extension propre, (“.sqlite”, “.db” sont de bonnes
pratiques)

Possibilité de sauvegarde en mémoire vive (extension
“:memory:”)

Objectif : remplacer le système de fichiers, mais pas les SGBDR

session sept 2014 Yann Caron (c) 2014 39


Architecture

Virtual Machine ?
Interface (API) Abstraction matérielle

OpCode (137

Ressources (Android)
instructions) Lexer Cacher


Arbre-B ? Compilation

Parser Gestionnaire B-Tree



Abstraction
matérielle CodeGen (opCode) Machine virtuelle

session sept 2014 Yann Caron (c) 2014 40


Notre bibliothèque avec SQLite

Le POJO Book public class Book {

// attributes

Un objet qui
private int id;
 private String title;
private String isbn;

représente un
private int nbPage;

// accessors

record “livre” public String getTitle() {


return title;
}


Des attributs, public void setTitle(String title) {
this.title = title;
}
des accesseurs, // etc.

un constructeur // constructor
public Book(int id) {
super(id);
stateless et un }

statefull
public Book(int id, String title, String isbn, int nbPage) {
this(id);
this.title = title;
this.isbn = isbn;
this.nbPage = nbPage;
}

session sept 2014 Yann Caron (c) 2014 41


Création de la base

Il faut fournir une classe qui a pour
responsabilité la création de la base et la mise
à jour du schéma
public class LibraryDBHelper extends SQLiteOpenHelper {

@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}

session sept 2014 Yann Caron (c) 2014 42


Création de la base

Une classe abstraite : SQLiteOpenHelper

Design pattern : Template method (GoF)

Un constructeur : données utiles

Deux méthodes abstraites :

onCreate : chargée de la création de la DB

onUpgrade : chargée de la mise à jour du schéma
(en général, on efface tout et on recommence)

session sept 2014 Yann Caron (c) 2014 43


Constructeur

Le context Android

Le nom du fichier

Le créateur de curseur (null par défaut)

La version

Un handler en cas de corruption de la base (par défaut)
public static final String DB_NAME = "Library.db";
public static final int DB_VERSION = 5;

// constructor
public LibraryDBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}

session sept 2014 Yann Caron (c) 2014 44


Création et Upgrade
public class LibraryDBHelper extends SQLiteOpenHelper {

public static final String DB_NAME = "Library.db";


public static final int DB_VERSION = 5;

public static String getQueryCreate() {


return "CREATE TABLE Book ("
+ "id Integer PRIMARY KEY AUTOINCREMENT, "
+ "title Text NOT NULL, "
+ "isbn Text NOT NULL, "
+ "nbPage Integer NOT NULL"
+ ");";
}

public static String getQueryDrop() {


return "DROP TABLE IF EXISTS Book;";
}

@Override Crée les tables


public void onCreate(SQLiteDatabase db) {
db.execSQL(getQueryCreate());
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(getQueryDrop());
db.execSQL(getQueryCreate());
} Recrée les tables
}
session sept 2014 Yann Caron (c) 2014 45
Gestion plus fine de l'upgrade

Des petits pas jusqu'à la version courante
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Management by successive upgrades
// newVersion is 4 !
int delta = newVersion - oldVersion;
if (delta >= 3) {
// upgrate to version 2
}

if (delta >= 2) { Gère les changements


// upgrate to version 3
}
étape par étape

if (delta >= 1) {
// upgrate to version 4
}
}

session sept 2014 Yann Caron (c) 2014 46


Datasource

Une classe responsable de l'accès à la base de
données

Responsable de créer le helper

Ouvrir (open())/Fermer (close())/Donner
accès aux données (getDB())

Factory des différents DAO

session sept 2014 Yann Caron (c) 2014 47


Datasource
public class LibraryDataSource {

private final LibraryDBHelper helper;



Crée le helper private SQLiteDatabase db;

public LibraryDataSource(Context context) {


helper = new LibraryDBHelper(context);

Accès à la db }

public SQLiteDatabase getDB() {


if (db == null) open(); // lazy initialization

Ouvre et ferme }
return db;
Accès à la base
la connexion public void open() throws SQLException {

}
db = helper.getWritableDatabase();


Les factories public void close() {

}
helper.close();
DAO factories
// factories
public BookDAO newBookDAO() {
return new BookDAO(this); // flyweight ?
}
}

session sept 2014 Yann Caron (c) 2014 48


DAO et CRUD

Référence la datasource

Create() : crée le record à partir du POJO, gestion de
son nouvel ID

Read() : lit le record selon l'ID et charge ses champs
avec les valeurs de la DB

Update() : met à jour les valeurs de la base à partir du
POJO

Delete() : supprime le record selon l'ID du POJO

session sept 2014 Yann Caron (c) 2014 49


Écrire la donnée

Une classe android.content.ContentValues

Tableau associatif (Set)

Clé : nom du champ en base

Valeur : valeur de la donnée dans le POJO

Une méthode put(String key, ???? value) pour
créer l'association (overload sur chaque type)

Des méthodes pour récupérer les valeurs selon les clés
(getAsInteger(), getAsDouble()…)

session sept 2014 Yann Caron (c) 2014 50


Méthode create() du DAO

Crée le tableau associatif avec les valeurs du
POJO

Exécute la requête d'insertion Tableau
associatif
Met à jour l'ID
Public synchronized Book create(Book POJO) {
 // create associative array
ContentValues values = new ContentValues();
values.put(COL_TITLE, POJO.getTitle());

Retourne le POJO
values.put(COL_ISBN, POJO.getIsbn());
 values.put(COL_NBPAGE, POJO.getNbPage());

// insert query

mis à jour
int id = (int) getDB().insert(TABLE_NAME, null, values);

// update id into POJO


POJO.setId(id); API level
return POJO;
}

session sept 2014 Yann Caron (c) 2014 51


Méthode update() du DAO

Le même principe que l'insert

La clause en plus
Public synchronized Book update(Book POJO) {
// create associative array
ContentValues values = new ContentValues();
values.put(COL_TITLE, POJO.getTitle());
values.put(COL_ISBN, POJO.getIsbn());
values.put(COL_NBPAGE, POJO.getNbPage());
Expression de recherche
// where clause
String clause = COL_ID + " = ?";
String[] clauseArgs = new String[]{String.valueOf(POJO.getId())};

// update
getDB().update(TABLE_NAME, values, clause, clauseArgs);

// return the POJO


return POJO;
}

session sept 2014 Yann Caron (c) 2014 52


Méthode delete() du DAO

Que la clause where, cette fois-ci !

Public synchronized void delete(Book POJO) {


// where clause
String clause = COL_ID + " = ?";
String[] clauseArgs = new String[]{String.valueOf(POJO.getId())};

// delete
getDB().delete(TABLE_NAME, clause, clauseArgs);
}

session sept 2014 Yann Caron (c) 2014 53


Lire la donnée

Deux méthodes :
➔ rawQuery (String query, String[] args)

Remplace les caractères “?” par les valeurs passées en argument

ex. : rawQuery(“SELECT * FROM book WHERE id = ?”, 1);
➔ query (String tableName, String[] columns,
String clause, String[] args, String groupBy,
String having, String orderBy)

Idée, le moins de SQL possible dans le code

Pourquoi pas un design pattern de Builder ou Interpreter ?

session sept 2014 Yann Caron (c) 2014 54


Cursor

La classe android.database.Cursor

Un design pattern Iterator

Sur une collection d'éléments typés (mais pas
nommés)

session sept 2014 Yann Caron (c) 2014 55


Méthode read() du DAO
public Book read(Book POJO) {
// columns
String[] allColumns = new String[]{COL_ID, COL_TITLE, COL_ISBN, COL_NBPAGE};

// clause
String clause = COL_ID + " = ?";
Expression de recherche
String[] clauseArgs = new String[]{String.valueOf(POJO.getId())};

// select query
Cursor cursor = getDB().query(TABLE_NAME, allColumns, "ID = ?", clauseArgs, null, null, null);

// read cursor
cursor.moveToFirst(); Requête
POJO.setTitle(cursor.getString(1));
POJO.setIsbn(cursor.getString(2));
POJO.setNbPage(cursor.getInt(3));
cursor.close(); Chargement du POJO
return POJO;
}

session sept 2014 Yann Caron (c) 2014 56


Méthode readAll() du DAO
public List<Book> readAll() {
// columns
String[] allColumns = new String[]{COL_ID, COL_TITLE, COL_ISBN, COL_NBPAGE};

// select query
Cursor cursor = getDB().query(TABLE_NAME, allColumns, null, null, null, null, null);

// iterate on cursor and retreive result


List<Book> books = new ArrayList<Book>();
Itération sur le recordset
cursor.moveToFirst();
while (!cursor.isAfterLast()) {

books.add(new Book(cursor.getInt(0), cursor.getString(1),


cursor.getString(2), cursor.getInt(3)));

cursor.moveToNext();
}

cursor.close();

return books;
}

session sept 2014 Yann Caron (c) 2014 57


Un peu de refactoring

Une classe abstraite public abstract class POJO {

protected int id;


commune à tous les public int getId() {

POJO
return id;
}

public void setId(int id) {



Une interface pour les }
this.id = id;

datasources public POJO(int id) {


this.id = id;
}
public interface DataSource { }

SQLiteDatabase getDB();
void open();
void close();

session sept 2014 Yann Caron (c) 2014 58


Un peu de refactoring
public abstract class DataAccessObject<P extends POJO> {


Une classe private final DataSource datasource;

public DataAccessObject(DataSource datasource) {


abstraite pour tous }
this.datasource = datasource;

les DAO public SQLiteDatabase getDB() {


return datasource.getDB();
}

Des interfaces // CRUD
public abstract P create(P POJO);

pour rajouter des public abstract P read(P POJO);

spécificités public abstract P update(P POJO);

public abstract void delete(P POJO);

Plus très loin d'un


}

ORM !
public interface AllReadeable<P extends POJO> {

List<P> readAll();

session sept 2014 Yann Caron (c) 2014 59


Avantages/Inconvénients

Avantages :

Séparation des responsabilités

Facile à maintenir ?

Inconvénients

Pas vraiment typés (String[] args)

Encore un peu de SQL par endroits (“id = ?”)

Mapping fastidieux, beaucoup de code à maintenir

BLOB (objet binaire) limité à 1Mb

session sept 2014 Yann Caron (c) 2014 60


IN01 – Séance 04

Object Relational Mapping

session sept 2014 Yann Caron (c) 2014 61


ORMLite

Object Relational Mapping

Basé sur des annotations (plus simple qu'Hibernate)

Facile à mettre en oeuvre

Lisible

Contre : intrusif, ne peut pas être appliqué à un objet dont
on ne possède pas les sources

Téléchargement : http://ormlite.com/releases/

Libraries : ormlite-core et ormlite-android

session sept 2014 Yann Caron (c) 2014 62


POJO

À quoi ressemble notre public class Book extends POJO {

// fields
nouveau POJO ? @DatabaseField(generatedId = true)
protected int id;
@DatabaseField(index = true)

Quelques annotations private String title;
@DatabaseField()
@DatabaseTable private String isbn;
@DatabaseField
Annotation
private int nbPage; de mapping
 @DatabaseField // etx ….


Un constructeur par // accessor
public int getId() {

défaut obligatoire }
return id;

public void setId(int id) {


this.id = id;
}
}

session sept 2014 Yann Caron (c) 2014 63


@DatabaseTable

Assure la correspondance entre le POJO, la
table et le DAO

Des paramètres à l'annotation :

tableName : spécifie le nom de la table (le nom de
la classe est utilisé par défaut)

daoClass : le nom de la classe du DAO

session sept 2014 Yann Caron (c) 2014 64


@DatabaseField

Permet de spécifier quels attributs doivent être
persistés

Des paramètres à l'annotation :

columnName : le nom du champ dans la base (le nom de
l'attribut est utilisé par défaut)

index : si le champ est indexé

generatedId : ID auto incrémental

canBeNull, foreign, unique ….

session sept 2014 Yann Caron (c) 2014 65


Le DBHelper
public class LibraryDBHelper extends OrmLiteSqliteOpenHelper {

public static final String DB_NAME = "Library.db";


public static final int DB_VERSION = 4;

public LibraryDBHelper(Context context) {


super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqld, ConnectionSource cs) {
try {
TableUtils.createTable(connectionSource, Book.class);
} catch (SQLException ex) {
throw new RuntimeException(ex);
} Factory automatique,
}
lien sur la classe
@Override
public void onUpgrade(SQLiteDatabase sqld, ConnectionSource cs, int i, int i1) {
try {
TableUtils.dropTable(connectionSource, Book.class, true);
TableUtils.createTable(connectionSource, Book.class);
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
}

session sept 2014 Yann Caron (c) 2014 66


OrmLiteSqliteOpenHelper

Doit hériter de la classe
OrmLiteSqliteOpenHelper

Même principe que pour SQLite, en charge de
créer ou d'upgrader le schéma de la base

Mais s'appuie sur les POJO pour la création
des tables : TableUtils.createTable

Et le drop : TableUtils.dropTable

session sept 2014 Yann Caron (c) 2014 67


Mise en œuvre

public class MainActivity extends OrmLiteBaseActivity<LibraryDBHelper> {

private void doSomeDBStuff() {


RuntimeExceptionDao<Book, Integer> bookDAO = getHelper().getDao(Book.class);

Book book1 = new Book(-1, "Croc Blanc", "2010034031", 248);


Book book2 = new Book(-1, "L'appel de la forêt", "2253039861", 158);

bookDAO.create(book1);
bookDAO.create(book2);
DAO factory

List<Book> books = bookDAO.queryForAll();


for (Book book : books) {
Log.w("READ ALL", book.toString()); Itération sur la liste
}
de POJO
Log.e("READ", bookDAO.queryForId(1).toString());
}
}
}

session sept 2014 Yann Caron (c) 2014 68


DAO

Un nouveau type d'activity
OrmLiteBaseActivity

Même principe qu'avec les DAO

Le DAO est récupéré auprès du helper

Meilleure gestion des appels multithreads

Utilise la méthode getDao(Class<T> clazz)

session sept 2014 Yann Caron (c) 2014 69


Méthodes du DAO

Les DAO ORMLite définissent plusieurs
méthodes :

create (T data) : C

queryForID (int id) : (R) requête sur l'identifiant

queryForEq (String fieldName, Object value) : (R)
requête sur une valeur

update (T data) : U

delete (T data) : D

session sept 2014 Yann Caron (c) 2014 70


PreparedStmt

Requêtes plus complexes

Utilisation de requêtes préparées
<T>
PreparedStmt

<T> <T> <T>


PreparedDelete PreparedQuery PreparedUpdate

session sept 2014 Yann Caron (c) 2014 71


QueryBuilder

Les requêtes préparées sont construites à partir de
fabriques

Classes QueryBuilder, UpdateBuilder, DeleteBuilder

méthodes de configuration de la requête : where(),
orderBy(), and(), or() ….

Une méthode prepare() permet de construire la requête
configurée

Enfin un design pattern Builder (GoF) pour construire les
requêtes

session sept 2014 Yann Caron (c) 2014 72


QueryBuilder

private void doOtherDBStuff() {


RuntimeExceptionDao<Book, Integer> bookDAO = getHelper().getBookDataDao();

QueryBuilder<Book, Integer> queryBuilder = bookDAO.queryBuilder();


Where<Book, Integer> where = queryBuilder.where();

where.and( Builder
where.eq("title", "Croc Blanc"),
where.or(
where.eq("nbPage", 248),
where.eq("nbPage", 317)
Prépare la requête
)
);

List<Book> books = bookDAO.query(queryBuilder.prepare());


for (Book book : books) {
Log.w("READ BY QUERY", book.toString());
}
}

session sept 2014 Yann Caron (c) 2014 73


Avantages/inconvénients ?

Avantages :

Séparation des responsabilités

Moins de code que précédemment (les POJO et un
helper)

Un builder pour créer les queries (plus de SQL)

Inconvénients

Pas vraiment typés non plus (where.eq)

Mapping Relationel/Objet = complexité supplémentaire

session sept 2014 Yann Caron (c) 2014 74


IN01 – Séance 04

NoSQL - OODBMS - DB4Object

session sept 2014 Yann Caron (c) 2014 75


DB4Object

Créé par Versant en 2000

Double licence : OpenSource GPL/Commerciale

Compatible Java et .net

Divers secteurs d'activités (Mobile, Navigation, SCADA, Devices and
equipments, Domotique)

Embarquable sur Android

NoSQL/OODBMS

Des outils de management (plugins Eclipse ou VisualStudio)

Réplication objet ou relationnelle

session sept 2014 Yann Caron (c) 2014 76


Réplication

Réplication
bidirectionnelle

Avec des SGBDR
via Hibernate

session sept 2014 Yann Caron (c) 2014 77


Performances

Réalisé par Versant, sur un graph complexe
d'objets et un héritage de 5 niveaux

session sept 2014 Yann Caron (c) 2014 78


Nos POJO

L'ID n'est plus public class Book {

nécessaire : // attributes
private String title;
private String isbn;
relations basées sur private int nbPage;

les pointeurs // accessors


public String getTitle() {
return title;
}

Réduit à sa plus public void setTitle(String title) {

simple expression }
this.title = title;

// etc.

// constructor ….

// toString ….

session sept 2014 Yann Caron (c) 2014 79


Mise en œuvre

user-permission WRITE_EXTERNAL_STORAGE

public static final String DB_FILE = root + "/db.db4o";

private void doSomeBookStuff(ObjectContainer db) {


Book book1 = new Book("Croc Blanc", "2010034031", 248);
Book book2 = new Book("L'appel de la forêt", "2253039861", 158);

db.store(book1); Méthode store()


db.store(book2);

ObjectSet<Book> result = db.queryByExample(Book.class);


for (Book p : result) {
textview.append("DB4O SELECT ALL Book " + p + " loaded !\n");
}
}
}

session sept 2014 Yann Caron (c) 2014 80


Mise en œuvre

La gestion du modèle devient inutile, DB4O se
charge de tout

Ou presque : veiller à toujours utiliser les mêmes
noms de classe, sinon prévoir de configurer la
transition

Insert ou Update automatique

session sept 2014 Yann Caron (c) 2014 81


Héritage
private void doSomeHierarchicalStuff(ObjectContainer db) {
Department root = new Department("T");
Department td = new Department("D");
Department to = new Department("O");

root.addChild(td);
root.addChild(to);

db.store(root);

db.store(new Person("Johanna", "Caron", 26));


db.store(new Employe(td, "Yann", "Caron", 34));

ObjectSet<Person> result = db.queryByExample(Person.class);


for (Person p : result) {
textview.append("DB4O HIERARCHICAL Object " + p + " loaded !\n");
}
}

session sept 2014 Yann Caron (c) 2014 82


Héritage

Un employé est une personne avec un
département rattaché

Les départements sont organisés de façon
hiérarchique (Design pattern composite)

Les relations sont établies sur les pointeurs
entre objets

Aucun mapping !

session sept 2014 Yann Caron (c) 2014 83


Mise en œuvre

La gestion du modèle devient inutile, DB4O se
charge de tout

Ou presque : veiller à toujours utiliser les mêmes
noms de classe, sinon prévoir de configurer la
transition

Insert ou Update automatique

session sept 2014 Yann Caron (c) 2014 84


Requêtes

Trois façons d'effectuer des requêtes :

QBE, Query By Example : le plus simple, on donne un objet
en exemple, et DB4O retourne tout ce qui y ressemble

NQ, Native Query : ressemble à du fonctionnel

SODA : Builder de bas niveau, base de construction des
deux précédentes

Vivement une implémentation pour le JDK8 (Map,
Filter, Reduce)

session sept 2014 Yann Caron (c) 2014 85


Query By Example

Principe : créer un objet vide

Ne renseigner que les champs qui sont l'objet
de la recherche

private void doQBEDBStuff(ObjectContainer db) {


ObjectSet<Book> result = db.queryByExample(new Book("Croc Blanc", null, 0));

for (Book p : result) {


textview.append("DB4O QBE Object " + p + " loaded !\n");
}
}

session sept 2014 Yann Caron (c) 2014 86


Native Query

Predicat ! Jointure ?
private void doNQDBStuff(ObjectContainer db) {
ObjectSet<Book> result = db.query(new Predicate<Book>() {
@Override
public boolean match(Book book) { Un prédicat
return "Croc Blanc".equals(book.getTitle());
}
});

for (Book p : result) {


textview.append("DB4O NQ1 Object " + p + " loaded !\n");
}

ObjectSet<Employe> result2 = db.query(new Predicate<Employe>() {

@Override
public boolean match(Employe person) {
textview.append("NQ2 PREDICATE departement = " + person.getDepartement().getName() + "\n");
return "TD".equals(person.getDepartement().getName());
}
});
for (Employe e : result2) {
textview.append("DB4O NQ2 Object " + e + " loaded !\n");
}
}
session sept 2014 Yann Caron (c) 2014 87
SODA

Ressemble au QueryBuilder vu précédemment

Plus puissant que les deux précédentes
méthodes
private void doSODADBStuff(ObjectContainer db) {
Query query = db.query();
query.constrain(Book.class);
query.descend("title").constrain("Croc Blanc").equal();

ObjectSet<Book> result = query.execute();

for (Book p : result) {


textview.append("DB4O SODA Object " + p + " loaded !\n");
}
}

session sept 2014 Yann Caron (c) 2014 88


Constat

Modèle complexe qui ne pose aucun problème de persistance

Le code est minimal

La mise à jour du modèle est automatique

La gestion create/update également

Types complexes (tout ce que l'on peut imaginer avec les objets)

Composite

Interpréter (faire persister des comportements à interpréter, des
formules de calculs par exemple)

Réseaux (réseaux de neurones ?)

session sept 2014 Yann Caron (c) 2014 89


Et bien plus encore

De bonnes performances annoncées

Un “foot print” de 1MB sur le disque

Une synchronisation prévue avec les SGBDR

Couche réseau optionnelle

Mode client/serveur

Publish/Subscribe pour synchroniser les clients

session sept 2014 Yann Caron (c) 2014 90


Pour aller plus loin !

Intégration avec les lambdas de Java 8 ?

Qu'en est-il des bases de données NoSQL de
type document :

JasDB

CouchDB → CouchBaseLite (plus complexe de
mise en œuvre que db4o)

SnappyDB : Clé/Valeurs, c'est tout !?!?

session sept 2014 Yann Caron (c) 2014 91


Bibliographie

SQLite : http://www.sqlite.org/

SQLite sur Developpez.com :
http://a-renouard.developpez.com/tutoriels/and
roid/sqlite/

SQLite-Sync : http://sqlite-sync.com/

db4objects : http://www.db4o.com/

session sept 2014 Yann Caron (c) 2014 92


Sources de la présentation

Trouvez toutes les sources de la présentation
sur Bitbucket
https://bitbucket.org/yann_caron/in01/src/

session sept 2014 Yann Caron (c) 2014 93


Fin
 Merci de votre attention
 Des questions ?

session sept 2014 Yann Caron (c) 2014 94

Vous aimerez peut-être aussi