I. Base de données locale▲
La base de données installée sur Android est SQLite, par contre, elle ne se pilote pas avec le JDBC usuel, mais avec un SGBDR (Système de Gestion de Base de Données Relationnelle) spécifique. Il faut modifier nos vieilles habitudes Java d'utilisateurs d'Hibernate, d'Ibatis ou de notre bon vieux JDBC. Une grosse différence concerne le typage des données de vos colonnes qui ne sera pas utilisé par SQLite (il l'est de manière indicative uniquement) : SQLite permet de stocker une valeur de n'importe quel type dans n'importe quelle colonne, quel que soit le type déclaré de cette colonne. D'autres différences : SQLite ne reconnait pas les contraintes de clefs étrangères, les transactions imbriquées, les jointures externes, certaines variantes d'ALTER TABLE…
Cf http://www.sqlite.org/docs.html et surtout http://www.sqlite.org/lang.html pour connaître la syntaxe à utiliser.
Comment cela marche-t-il ?
La base de données est liée à votre activité (pour pouvoir partager son accès, il faut mettre en place un ContentProvider, cela sera explicité dans un autre chapitre), c'est elle qui la crée, la met à jour, la remplit, l'interroge et la clôt. Ainsi dans le onCreate de votre activité vous appelez votre base. Si celle-ci n'existe pas, le code que vous avez implémenté pour la créer est appelé. Si sa structure a évolué, le code que vous avez écrit pour la mettre à jour est appelé. Quand vous récupérez votre base, vous la manipulez au travers d'une classe spécifique qui encapsule les appels que vous avez écrits (votre DAO). Quand vous quittez votre activité, dans la méthode Destroy, vous fermez votre base.
Dans la pratique cela implique au moins deux classes spécifiques :
· votre classe de création et de mise à jour de la base (de la structure de la base) qui étend SQLiteHelper. N'oubliez pas de mettre votre clef primaire technique unique qui s'auto-incrémente pour chacune de vos tables. Enfin, il est préconisé que tous vos noms de tables, de colonnes de la base soient des variables public final static de votre classe. Cette classe implémente au moins trois méthodes :
o le constructeur qui appelle son super (et qui prend en paramètre le numéro de version de la structure de la base),
o onCreate qui crée la base si elle n'existe pas,
o onUpdate qui met à jour votre structure de table si celle-ci a évolué. Pour savoir si elle a évolué, un numéro de version de la structure de la base est utilisé. En effet elle prend en paramètre un oldVersion et un newVersion ;
· votre classe DAO (vos classes DAO) qui encapsule vos appels à la base. Deux manières d'obtenir votre base de données sont à votre disposition :
o getWritableDatabase() pour l'obtenir en mode écriture (mais du coup évidemment c'est un mode lecture/écriture),
o getReadableDatabase() pour l'obtenir en mode lecture seule.
Enfin, souvenez-vous que vous devez utiliser les méthodes beginTransaction, endTransaction et commitTransaction si vous faites des traitements qui ne sont pas atomiques.
I-A. Ouverture et fermeture▲
private
SQLiteDatabase db;
@
Override
public
void
open
(
) throws
SQLiteException {
try
{
db =
dbHelper.getWritableDatabase
(
);
}
catch
(
SQLiteException ex) {
db =
dbHelper.getReadableDatabase
(
);
}
}
public
void
close
(
) {
db.close
(
);
}
Où la classe DBHelper est votre classe de création de la base qui étend SQLiteHelper. (cf. ci-dessous pour l'explication.)
I-B. Création et mise à jour de la structure de la base▲
Commençons par un exemple :
public
class
DBOpenHelper extends
SQLiteOpenHelper {
/**
@goals
This
class
aims
to
show
the
constant
to
use
for
the
DBOpenHelper
*/
public
static
class
Constants implements
BaseColumns {
/**
The
database
name
*/
public
static
final
String DATABASE_NAME =
"
myData.db
"
;
/**
The
database
version
*/
public
static
final
int
DATABASE_VERSION =
1
;
/**
The
table
Name
*/
public
static
final
String MY_TABLE =
"
Human
"
;
//
Column
name.
/**
My
Column
ID
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_ID =
"
_id
"
;//
Mandatory
/**
My
Column
Name
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_NAME =
"
name
"
;
/**
My
Column
First
Name
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_FIRSTNAME =
"
firstName
"
;
/**
My
Column
Eyes
Color
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_EYES_COLOR =
"
eyesColor
"
;
/**
My
Column
Hair
color
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_HAIR_COLOR =
"
hairColor
"
;
/**
My
Column
age
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_AGE =
"
age
"
;
//
Indexes
des
colonnes
/**
The
index
of
the
column
ID
*/
public
static
final
int
ID_COLUMN =
1
;
/**
The
index
of
the
column
NAME
*/
public
static
final
int
NAME_COLUMN =
2
;
/**
The
index
of
the
column
FIRST
NAME
*/
public
static
final
int
FIRSTNAME_COLUMN =
3
;
/**
The
index
of
the
column
EYES
COLOR
*/
public
static
final
int
EYES_COLOR_COLUMN =
4
;
/**
The
index
of
the
column
HAIR
COLOR
*/
public
static
final
int
HAIR_COLOR_COLUMN =
5
;
/**
The
index
of
the
column
AGE
*/
public
static
final
int
AGE_COLUMN =
6
;
}
//
The
static
string
to
create
the
database.
private
static
final
String DATABASE_CREATE =
"
create
table
"
+
Constants.MY_TABLE +
"
(
"
+
Constants.KEY_COL_ID+
"
integer
primary
key
autoincrement,
"
+
Constants.KEY_COL_AGE +
"
INTEGER,
"
+
Constants.KEY_COL_NAME+
"
TEXT,
"
+
Constants.KEY_COL_FIRSTNAME +
"
TEXT,
"
+
Constants.KEY_COL_EYES_COLOR +
"
TEXT,
"
+
Constants.KEY_COL_HAIR_COLOR +
"
TEXT)
"
;
/**
*
@param
context
=
the
context
of
the
caller
*
@param
name
=
Database
'
s
name
*
@param
factory
=
null
*
@param
version
=
Database
'
s
version
*/
public
DBOpenHelper
(
Context context, String name, CursorFactory factory, int
version) {
super
(
context, name, factory, version);
}
/*
*
(non-Javadoc)
*
*
@see*
android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
*/
@
Override
public
void
onCreate
(
SQLiteDatabase db) {
//
Create
the
new
database
using
the
SQL
string
Database_create
db.execSQL
(
DATABASE_CREATE);
}
/*
*
(non-Javadoc)
*
*
@see
*
android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase,int,
int)
*/
@
Override
public
void
onUpgrade
(
SQLiteDatabase db, int
oldVersion, int
newVersion) {
Log.w
(
"
DBOpenHelper
"
, "
Mise
à
jour
de
la
version
"
+
oldVersion +
"
vers
la
version
"
+
newVersion
+
"
,
les
anciennes
données
seront
détruites
"
);
//
Drop
the
old
database
db.execSQL
(
"
DROP
TABLE
IF
EXISTS
"
+
Constants.MY_TABLE);
//
Create
the
new
one
onCreate
(
db);
//
or
do
a
smartest
stuff
}
}
Qui est appelé par votre activité par :
dbOpenHelper =
new
DBOpenHelper
(
this
, Constants.DATABASE_NAME, null
,
Constants.DATABASE_VERSION);
Où :
· Context est le contexte de votre activité (this quand vous êtes dans votre activité) ;
· le nom de votre base de données ;
· une fabrique de cureurs (le plus souvent null) ;
· la version de la structure de votre base.
La syntaxe de création est la suivante :

Ainsi l'exemple précédent crée une table dont le nom est DATABASE_TABLE avec une colonne KEY_ID qui est la clef primaire de type entier qui s'auto-incrémente, une colonne KEY_TASK de type string, non null, et une colonne KEY_CREATION_DATE de type long.
De plus voilà la syntaxe complète de création d'une table µSQLite :
Collumn-def :

Type-name :

Column-constraint :

Table-constraint :

ForeignKey clauses :

I-C. Gérer l'instanciation et l'ouverture▲
Pour la création et l'instanciation d'une base de données :
/**
*
The
database
*/
private
SQLiteDatabase db;
/**
*
The
database
creator
and
updater
helper
*/
DBOpenHelper dbOpenHelper;
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
//
Create
or
retrieve
the
database
dbOpenHelper =
new
DBOpenHelper
(
this
, Constants.DATABASE_NAME, null
,
Constants.DATABASE_VERSION);
//
open
the
database
openDB
(
);
//
Insert
a
new
record
//
-------------------
ContentValues contentValues =
new
ContentValues
(
);
long
rowId =
insertRecord
(
contentValues);
//
update
that
line
//
----------------
rowId =
updateRecord
(
contentValues, rowId);
//
Query
that
line
//
---------------
queryTheDatabase
(
);
//
And
then
delete
it:
//
-------------------
deleteRecord
(
rowId);
}
I-D. Mise à jour des données de la table : Insert, Update et Delete de la classe SQLiteDatabase▲
Pour l'insert :
//
Crée
une
nouvelle
ligne
à
insérer.
ContentValues newTaskValues =
new
ContentValues
(
);
//
Assign
the
values
for
each
column.
contentValues.put
(
Constants.KEY_COL_NAME,"
name
"
);
contentValues.put
(
Constants.KEY_COL_FIRSTNAME, "
firstName
"
);
contentValues.put
(
Constants.KEY_COL_EYES_COLOR, "
green
"
);
contentValues.put
(
Constants.KEY_COL_HAIR_COLOR, "
blond
"
);
contentValues.put
(
Constants.KEY_COL_AGE, 6
);
//
Insert
the
line
in
the
database
long
rowId=
db.insert
(
Constants.MY_TABLE, null
, contentValues);
//
test
to
see
if
the
insertion
was
ok
if
(
rowId=
=
-
1
){
Toast.makeText
(
this
, "
Error
when
creating
an
human
"
, Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
created
and
stored
in
database
"
, Toast.LENGTH_LONG).show
(
);
}
return
rowId;
On définit un objet ContentValues dans lequel on place des paires (NomDeColonne, Valeur) à créer. Puis on utilise notre objet SQLiteDatabase pour faire l'insert en lui passant, le nom de la table, le nom d'une colonne (souvent null) et l'objet contenant la carte des paires (colonne, valeur) à insérer.
Pour l'update :
contentValues.clear
(
);
contentValues.put
(
Constants.KEY_COL_NAME,"
Georges
"
);
contentValues.put
(
Constants.KEY_COL_FIRSTNAME, "
Walter
Bush
"
);
//
update
the
database
rowId=
db.update
(
Constants.MY_TABLE, contentValues, Constants.KEY_COL_ID +
"
=
"
+
rowId, null
);
//
test
to
see
if
the
insertion
was
ok
if
(
rowId=
=
-
1
){
Toast.makeText
(
this
, "
Error
when
updating
an
human
"
, Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
updated
in
database
"
, Toast.LENGTH_LONG).show
(
);
}
return
rowId;
On définit l'objet ContentValues dans lequel on place des paires (NomDeColonne, Valeur) à mettre à jour. Puis on utilise notre objet SQLiteDatabase pour faire l'update en lui passant le nom de la table, les valeurs à mettre et la clause where (ici la clef primaire de l'objet).
Pour le delete :
rowId=
db.delete
(
DBOpenHelper.Constants.MY_TABLE,DBOpenHelper.Constants.KEY_COL_ID +
"
=
"
+
rowId, null
);
if
(
rowId=
=
-
1
){
Toast.makeText
(
this
, "
Error
when
deleting
an
human
"
, Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
deleted
in
database
"
, Toast.LENGTH_LONG).show
(
);
}
On utilise notre objet SQLiteDatabase pour faire le delete en lui passant le nom de la table et la clause where (ici la clef primaire de l'objet).
I-D-1. Javadoc▲
public long insert (String table, String nullColumnHack, ContentValues values)
Since: API Level 1
Convenience method for inserting a row into the database.
Parameters
table |
the table to insert the row into |
nullColumnHack |
SQL doesn't allow inserting a completely empty row, so if initialValues is empty this column will explicitly be assigned a NULL value |
values |
this map contains the initial column values for the row. The keys should be the column names and the values the column values |
Returns
the row ID of the newly inserted row, or -1 if an error occurred
public int update (String table, ContentValues values, String whereClause, String[] whereArgs)
Since: API Level 1
Convenience method for updating rows in the database.
Parameters
table |
the table to update in |
values |
a map from column names to new column values. null is a valid value that will be translated to NULL. |
whereClause |
the optional WHERE clause to apply when updating. Passing null will update all rows. |
Returns
the number of rows affected
public int delete (String table, String whereClause, String[] whereArgs)
Since: API Level 1
Convenience method for deleting rows in the database.
Parameters
table |
the table to delete from |
whereClause |
the optional WHERE clause to apply when deleting. Passing null will delete all rows. |
Returns
the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause.
I-E. Récupération des données de la table Query de la classe SQLiteDatabase▲
I-E-1. Parcourir le résultat des requêtes▲
Les résultats de requêtes sont renvoyés sous forme d'une liste de pointeurs vers les objets retournés. Cette liste de pointeurs se nomme Cursor. Cette classe possède de nombreuses méthodes :
· de mouvements (moveToFirst, moveToLast, moveNext, movePrevious, moveToPosition(int index)) ;
· de récupérations (getDouble, getFloat, getInt, getLong, getShort, getString, getBlob) ;
· d'informations (getColunmCount, getColumnName, getColumnIndex, getPosition, getCount…) ;
· d'états (isAfterLast, isBeforeFirst, isClosed, isFirst, isLast, isNull) ;
· d'autres méthodes de gestion de l'objet Cursor lui-même.
L'amalgame entre la liste de curseurs et la position du curseur est clair. On bouge dans la liste et en même temps quand on pointe sur un élément on l'interroge. Il faut s'y faire :
Cursor cursor =
db.query
(
Constants.MY_TABLE,projections ,selection, selectionArg, groupBy,having,orderBy, maxResultsListSize);
//
then
browse
the
result:
if
(
cursor.moveToFirst
(
)){
//
The
elements
to
retrieve
Integer colId;
String name;
String firstname;
//
The
associated
index
within
the
cursor
int
indexId=
cursor.getColumnIndex
(
Constants.KEY_COL_ID);
int
indexName=
cursor.getColumnIndex
(
Constants.KEY_COL_NAME);
int
indexFirstName=
cursor.getColumnIndex
(
Constants.KEY_COL_FIRSTNAME);
//
Browse
the
results
list:
int
count=
0
;
do
{
colId=
cursor.getInt
(
indexId);
name=
cursor.getString
(
indexName);
firstname=
cursor.getString
(
indexFirstName);
Toast.makeText
(
this
, "
Retrieve
element
:
"
+
name+
"
,
"
+
firstname+
"
(
"
+
colId+
"
)
"
, Toast.LENGTH_LONG).show
(
);
count+
+
;
}
while
(
cursor.moveToNext
(
));
Toast.makeText
(
this
, "
The
number
of
elements
retrieved
is
"
+
count, Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
No
element
found
:
"
, Toast.LENGTH_LONG).show
(
);
}
I-E-2. Effectuer une requête à la main▲
Il faut utiliser la méthode query de SQLiteDatabase.
Cette méthode prend en paramètres les éléments suivants :
· un booléen optionnel spécifiant si le résultat se compose d'éléments uniques (Boolean) ;
· le nom de la table à interroger (String) ;
· une projection sous forme de tableau de chaines listant les colonnes à inclure dans le résultat (String[]) ;
· une clause where avec des jokers (?) pour les paramètres si vous le souhaitez (String) ;
· la liste des paramètres qui remplaceront les jokers (?)(String[]) ;
· une clause groupBy (String) ;
· une clause orderBy dont la syntaxe est nomDeColonne + « ASC||Desc »(String) ;
· une limite maximale optionnelle du nombre d'éléments à récupérer (String).
Un exemple :
//
Using
man
made
query
//
The
projection
define
what
are
the
column
you
want
to
retrieve
String[] projections=
new
String[] {
Constants.KEY_COL_ID, Constants.KEY_COL_NAME, Constants.KEY_COL_FIRSTNAME }
;
//
And
then
store
the
column
index
answered
by
the
request
(we
present
an
other
way
to
retireve
data)
final
int
cursorIdColNumber=
0
,cursorNameColNumber=
1
,cursorFirstNameColNumber=
2
;
//
To
add
a
Where
clause:
String selection=
Constants.KEY_COL_HAIR_COLOR+
"
=?
"
;
String[] selectionArg=
new
String[] {
"
blond
"
}
;
//
The
groupBy
clause:
String groupBy=
Constants.KEY_COL_EYES_COLOR;
//
The
having
clause
String having=
null
;
//
The
order
by
clause
(column
name
followed
by
Asc
or
DESC)
String orderBy =
Constants.KEY_COL_AGE+
"
ASC
"
;
//
Maximal
size
of
the
results
list
String maxResultsListSize=
"
60
"
;
Cursor cursor =
db.query
(
Constants.MY_TABLE,projections ,selection, selectionArg, groupBy,having,orderBy, maxResultsListSize);
displayResults
(
cursor);
I-E-3. Effectuer une requête avec SQLiteQueryBuilder▲
Vous pouvez utiliser aussi l'objet SQLiteQueryBuilder qui permet d'effectuer des unions et quelques autres opérations de ce type.
Nous reprenons dans l'exemple uniquement une recherche simple :
//
Using
SQLiteQueryBuilder
//
The
projection
define
what
are
the
column
you
want
to
retrieve
String[] projections=
new
String[] {
Constants.KEY_COL_ID, Constants.KEY_COL_NAME, Constants.KEY_COL_FIRSTNAME }
;
//
And
then
store
the
column
index
answered
by
the
request
(we
present
an
other
way
to
retireve
data)
final
int
cursorIdColNumber=
0
,cursorNameColNumber=
1
,cursorFirstNameColNumber=
2
;
//
Adding
a
where
clause:
String selection=
Constants.KEY_COL_HAIR_COLOR+
"
=?
"
;
String[] selectionArg=
new
String[] {
"
blond
"
}
;
//
The
groupBy
clause:
String groupBy=
Constants.KEY_COL_EYES_COLOR;
//
The
having
clause
String having=
null
;
//
The
order
by
clause
(column
name
followed
by
Asc
or
DESC)
String orderBy =
Constants.KEY_COL_AGE+
"
ASC
"
;
//
Using
the
QueryBuilder
//
Create
a
Query
SQLite
object
SQLiteQueryBuilder qb =
new
SQLiteQueryBuilder
(
);
qb.setTables
(
Constants.MY_TABLE);
//
qb.appendWhere(Constants.KEY_COL_HAIR_COLOR+
"=blond");
qb.setDistinct
(
true
);
cursor=
qb.query
(
db,projections ,selection, selectionArg, groupBy,having,orderBy);
displayResults
(
cursor);
I-F. Gestion des transactions▲
Les transactions peuvent avoir un listener, ce qui est une bonne pratique, mais vous pouvez vous en passer (ce qui est une mauvaise pratique).
Le pattern standard d'utilisation des transactions est :
soit :
db.beginTransactionWithListener
(
listener);
soit :
db.beginTransaction
(
);
try
{
...
db.setTransactionSuccessful
(
);
}
finally
{
db.endTransaction
(
);
}
Le listener est du type :
public void beginTransactionWithListener (SQLiteTransactionListener transactionListener)
I-G. Un exemple complet▲
Cet exemple montre comment mettre en place une base de données et communiquer avec elle à partir d'une activité. Il y a deux classes, la classe d'instanciation de la base et la classe d'utilisation de cette base.
La classe de création :
public
class
DBOpenHelper extends
SQLiteOpenHelper {
/**
@goals
This
class
aims
to
show
the
constant
to
use
for
the
DBOpenHelper
*/
public
static
class
Constants implements
BaseColumns {
/**
The
database
name
*/
public
static
final
String DATABASE_NAME =
"
myData.db
"
;
/**
The
database
version
*/
public
static
final
int
DATABASE_VERSION =
1
;
/**
The
table
Name
*/
public
static
final
String MY_TABLE =
"
Human
"
;
//
Noms
de
colonnes
//
/!\Si
vous
utilisez
une
base
de
données,
les
noms
des
colonnes
ont
les
mêmes
que
ceux
de
//
votre
base,
de
même
pour
les
index.
/**
My
Column
ID
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_ID =
"
_id
"
;//
Mandatory
/**
My
Column
Name
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_NAME =
"
name
"
;
/**
My
Column
First
Name
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_FIRSTNAME =
"
firstName
"
;
/**
My
Column
Eyes
Color
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_EYES_COLOR =
"
eyesColor
"
;
/**
My
Column
Hair
color
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_HAIR_COLOR =
"
hairColor
"
;
/**
My
Column
age
and
the
associated
explanation
for
end
-
users
*/
public
static
final
String KEY_COL_AGE =
"
age
"
;
//
Index
des
colonnes
/**
The
index
of
the
column
ID
*/
public
static
final
int
ID_COLUMN =
1
;
/**
The
index
of
the
column
NAME
*/
public
static
final
int
NAME_COLUMN =
2
;
/**
The
index
of
the
column
FIRST
NAME
*/
public
static
final
int
FIRSTNAME_COLUMN =
3
;
/**
The
index
of
the
column
EYES
COLOR
*/
public
static
final
int
EYES_COLOR_COLUMN =
4
;
/**
The
index
of
the
column
HAIR
COLOR
*/
public
static
final
int
HAIR_COLOR_COLUMN =
5
;
/**
The
index
of
the
column
AGE
*/
public
static
final
int
AGE_COLUMN =
6
;
}
//
The
static
string
to
create
the
database.
private
static
final
String DATABASE_CREATE =
"
create
table
"
+
Constants.MY_TABLE +
"
(
"
+
Constants.KEY_COL_ID+
"
integer
primary
key
autoincrement,
"
+
Constants.KEY_COL_AGE +
"
INTEGER,
"
+
Constants.KEY_COL_NAME+
"
TEXT,
"
+
Constants.KEY_COL_FIRSTNAME +
"
TEXT,
"
+
Constants.KEY_COL_EYES_COLOR +
"
TEXT,
"
+
Constants.KEY_COL_HAIR_COLOR +
"
TEXT)
"
;
/**
*
@param
context
*
@param
name
*
@param
factory
*
@param
version
*/
public
DBOpenHelper
(
Context context, String name, CursorFactory factory, int
version) {
super
(
context, name, factory, version);
}
/*
*
*
(non-Javadoc)
*
@see*
*
android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
*/
@
Override
public
void
onCreate
(
SQLiteDatabase db) {
//
Create
the
new
database
using
the
SQL
string
Database_create
db.execSQL
(
DATABASE_CREATE);
}
/*
*
*
(non-Javadoc)
*
@see
*
*
android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite
*
.SQLiteDatabase,int,
int)
*/
@
Override
public
void
onUpgrade
(
SQLiteDatabase db, int
oldVersion, int
newVersion) {
Log.w
(
"
DBOpenHelper
"
, "
Mise
à
jour
de
la
version
"
+
oldVersion +
"
vers
la
version
"
+
newVersion
+
"
,
les
anciennes
données
seront
détruites
"
);
//
Drop
the
old
database
db.execSQL
(
"
DROP
TABLE
IF
EXISTS
"
+
Constants.MY_TABLE);
//
Create
the
new
one
onCreate
(
db);
//
or
do
a
smartest
stuff
}
}
La classe d'utilisation :
public
class
DataBaseTuto extends
Activity {
/**
*
The
database
*/
private
SQLiteDatabase db;
/**
*
The
database
creator
and
updater
helper
*/
DBOpenHelper dbOpenHelper;
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
//
Create
or
retrieve
the
database
dbOpenHelper =
new
DBOpenHelper
(
this
, Constants.DATABASE_NAME, null
, Constants.DATABASE_VERSION);
//
open
the
database
openDB
(
);
//
Insert
a
new
record
//
-------------------
ContentValues contentValues =
new
ContentValues
(
);
long
rowId =
insertRecord
(
contentValues);
//
update
that
line
//
----------------
rowId =
updateRecord
(
contentValues, rowId);
//
Query
that
line
//
---------------
queryTheDatabase
(
);
//
And
then
delete
it:
//
-------------------
deleteRecord
(
rowId);
}
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
Managing
LifeCycle
and
database
open
/
close
operations
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/*
*
(non-Javadoc)**
@see
android.app.Activity#onResume()
*/
@
Override
protected
void
onResume
(
) {
super
.onResume
(
);
openDB
(
);
}
/*
*
(non-Javadoc)**
@see
android.app.Activity#onPause()
*/
@
Override
protected
void
onPause
(
) {
super
.onPause
(
);
closeDB
(
);
}
/**
*
Open
the
database
*
*
*
@throws
SQLiteException
*/
public
void
openDB
(
) throws
SQLiteException {
try
{
db =
dbOpenHelper.getWritableDatabase
(
);
}
catch
(
SQLiteException ex) {
db =
dbOpenHelper.getReadableDatabase
(
);
}
}
/**
*
Close
Database
*/
public
void
closeDB
(
) {
db.close
(
);
}
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
Managing
Records
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
Insert
a
record
*
*
@param
contentValues
*
(
an
empty
contentValues
)
*
@return
the
inserted
row
id
*/
private
long
insertRecord
(
ContentValues contentValues) {
//
Assign
the
values
for
each
column.
contentValues.put
(
Constants.KEY_COL_NAME, "
name
"
);
contentValues.put
(
Constants.KEY_COL_FIRSTNAME, "
firstName
"
);
contentValues.put
(
Constants.KEY_COL_EYES_COLOR, "
green
"
);
contentValues.put
(
Constants.KEY_COL_HAIR_COLOR, "
blond
"
);
contentValues.put
(
Constants.KEY_COL_AGE, 6
);
//
Insert
the
line
in
the
database
long
rowId =
db.insert
(
Constants.MY_TABLE, null
, contentValues);
//
test
to
see
if
the
insertion
was
ok
if
(
rowId =
=
-
1
) {
Toast.makeText
(
this
, "
Error
when
creating
an
human
"
,
Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
created
and
stored
in
database
"
,
Toast.LENGTH_LONG).show
(
);
}
return
rowId;
}
/**
*
*
Update
a
record
*
*
@param
contentValues
*
@param
rowId
*
@return
the
updated
row
id
*/
private
long
updateRecord
(
ContentValues contentValues, long
rowId) {
contentValues.clear
(
);
contentValues.put
(
Constants.KEY_COL_NAME, "
Georges
"
);
contentValues.put
(
Constants.KEY_COL_FIRSTNAME, "
Walter
Bush
"
);
//
update
the
database
rowId =
db.update
(
Constants.MY_TABLE, contentValues,
Constants.KEY_COL_ID +
"
=
"
+
rowId, null
);
//
test
to
see
if
the
insertion
was
ok
if
(
rowId =
=
-
1
) {
Toast.makeText
(
this
, "
Error
when
updating
an
human
"
,
Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
updated
in
database
"
, Toast.LENGTH_LONG).show
(
);
}
return
rowId;
}
/**
*
Delete
a
Record
*
*
@param
rowId
*/
private
void
deleteRecord
(
long
rowId) {
rowId =
db.delete
(
DBOpenHelper.Constants.MY_TABLE,
DBOpenHelper.Constants.KEY_COL_ID +
"
=
"
+
rowId, null
);
if
(
rowId =
=
-
1
) {
Toast.makeText
(
this
, "
Error
when
deleting
an
human
"
,
Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
Human
deleted
in
database
"
, Toast.LENGTH_LONG).show
(
);
}
}
/**
*
Query
a
the
database
*/
private
void
queryTheDatabase
(
) {
//
Using
man
made
query
//
The
projection
define
what
are
the
column
you
want
to
retrieve
String[] projections =
new
String[] {
Constants.KEY_COL_ID, Constants.KEY_COL_NAME,
Constants.KEY_COL_FIRSTNAME }
;
//
And
then
store
the
column
index
answered
by
the
request
(we
present
an
other
way
to
//
retireve
data)
final
int
cursorIdColNumber =
0
,
cursorNameColNumber =
1
,
cursorFirstNameColNumber =
2
;
//
To
add
a
Where
clause
you
can
either
do
that:
//
qb.appendWhere(Constants.KEY_COL_HAIR_COLOR+
"=blond");
//
Or
that:
String selection =
Constants.KEY_COL_HAIR_COLOR +
"
=?
"
;
String[] selectionArg =
new
String[] {
"
blond
"
}
;
//
The
groupBy
clause:
String groupBy =
Constants.KEY_COL_EYES_COLOR;
//
The
having
clause
String having =
null
;
//
The
order
by
clause
(column
name
followed
by
Asc
or
DESC)
String orderBy =
Constants.KEY_COL_AGE +
"
ASC
"
;
//
Maximal
size
of
the
results
list
String maxResultsListSize =
"
60
"
;
Cursor cursor =
db.query
(
Constants.MY_TABLE, projections, selection, selectionArg,
groupBy, having, orderBy,maxResultsListSize);
displayResults
(
cursor);
//
Using
the
QueryBuilder
//
Create
a
Query
SQLite
object
SQLiteQueryBuilder qb =
new
SQLiteQueryBuilder
(
);
qb.setTables
(
Constants.MY_TABLE);
//
qb.appendWhere(Constants.KEY_COL_HAIR_COLOR+
"=blond");
qb.setDistinct
(
true
);
cursor =
qb.query
(
db, projections, selection, selectionArg, groupBy, having, orderBy);
displayResults
(
cursor);
}
/**
*
Display
the
results
stored
in
the
cursor
*
*
@param
cursor
*/
private
void
displayResults
(
Cursor cursor) {
//
then
browse
the
result:
if
(
cursor.moveToFirst
(
)) {
//
The
elements
to
retrieve
Integer colId;
String name;
String firstname;
//
The
associated
index
within
the
cursor
int
indexId =
cursor.getColumnIndex
(
Constants.KEY_COL_ID);
int
indexName =
cursor.getColumnIndex
(
Constants.KEY_COL_NAME);
int
indexFirstName =
cursor.getColumnIndex
(
Constants.KEY_COL_FIRSTNAME);
//
Browse
the
results
list:
int
count =
0
;
do
{
colId =
cursor.getInt
(
indexId);
name =
cursor.getString
(
indexName);
firstname =
cursor.getString
(
indexFirstName);
Toast.makeText
(
this
, "
Retrieve
element
:
"
+
name +
"
,
"
+
firstname +
"
(
"
+
colId +
"
)
"
,Toast.LENGTH_LONG).show
(
);
count+
+
;
}
while
(
cursor.moveToNext
(
));
Toast.makeText
(
this
, "
The
number
of
elements
retrieved
is
"
+
count,
Toast.LENGTH_LONG).show
(
);
}
else
{
Toast.makeText
(
this
, "
No
element
found
:
"
, Toast.LENGTH_LONG).show
(
);
}
}
}
II. Android2EE: La Formation et l'Expertise Android à votre service▲
![]() |
Android2EE
|
|
III. Récupération des tutoriels et lecture des autres chapitres du livre▲
Vous pouvez lire l'ensemble de l'ouvrage sur Android2EE, à cet adresse Livre en consultation. Les 28 chapitres sont disponibles. Un tutorial sera bientôt disponible sur le site Android2EE.
IV. Le site Android2ee, une référence pour le développement Android.▲
Le site Android2EE vous propose des tutoriels, des articles, des vidéos, des conférences, des eBooks en libre consultation pour monter en compétence sur la technologie Android.
Vous trouverez tout cela dans la partie « Open Resources ».
N'hésitez plus visitez-le ! Android2EE
V. Remerciements▲
Nous remercions Claude Leloup pour sa relecture orthographique.
N'hésitez pas à commenter cet article ! Commentez