ORMLite is a lite version of an ORM tool to manipulate database access. It provides DAO's and SQL commands and you don't need to program it by yourself. It saves a lot of time. I was really surprised how easy it was to implement it. Because i think this a really nice tool, i want to share my expirience with you. I also solved the problem of saving complex objects with it. The example bellow is a little proof of concept i did. I use ORMLite to manage Entities, generate DTO's automatically and to facilitate communication between SQLite (database) and Application. The following link describes the use ORMLite: http://ormlite.com/javadoc/ormlite-core/doc-files/ormlite_4.html#Use-With-Android
Installation of ORMLite:
1. Download libraries ormlite-core.jar and ormlite-android.jar
2. Copy the libraries into folder libs of your android project. (Android will auto-reference it)
3. Create the desired entities and annotate them appropriately as in the following example: (make sure that the default-constructors were defined as ORMLite requires them to their proper operation.)
import java.util.Date;
import com.j256.ormlite.field.DatabaseField;
import
com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "contato")
public class ContatoEntity {
// generatedId set to false, because we will get it from the server!
@DatabaseField(id = true, generatedId = false)
public int id;
@DatabaseField public String descricao;
@DatabaseField public String ddi;
@DatabaseField public String ddd;
@DatabaseField public Date timestamp;
public ContatoEntity() {/*OrmLite need a default constructor*/}
}
import
com.j256.ormlite.field.DatabaseField;
import
com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "pessoa")
public class PessoaEntity {
@DatabaseField(id = true, generatedId = false)
public int id;
@DatabaseField public String nome;
@DatabaseField(canBeNull = false, foreign = true)
public
TipoPessoaEntity tpPessoa;
public PessoaEntity() {/*OrmLite need a default constructor*/}
//Atention: Take a special look at the annotation of tpPessoa bellow! we will discuss it later! |
import
com.j256.ormlite.field.DatabaseField;
import
com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "pessoa")
public class PessoaEntity {
@DatabaseField(id = true, generatedId = false) public int id;
@DatabaseField public String nome;
@DatabaseField(canBeNull = false, foreign = true,foreignAutoCreate = true,foreignAutoRefresh =
true)
public TipoPessoaEntity tpPessoa;
public PessoaEntity() {/*OrmLite need a
default constructor*/}Create a proper DatabaseOpenHelper
You helper must extend from OrmLiteSqliteOpenHelper as in the following example:
public class DatabaseHelper extends
OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME
= "db_mobtur.db";
private static final int DATABASE_VERSION = 1;
public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME,
null,
DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db,
ConnectionSource connectionSource) {
try {
Log.i(DatabaseHelper.class.getName(), "onCreate");
TableUtils.createTable(connectionSource,
ContatoEntity.class);
TableUtils.createTable(connectionSource,
PessoaEntity.class);
TableUtils.createTable(connectionSource,
TipoPessoaEntity.class);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public void onUpgrade(SQLiteDatabase db,
ConnectionSource connectionSource, int oldVersion, int newVersion) {
try {
Log.i(DatabaseHelper.class.getName(), "onUpgrade");
TableUtils.dropTable(connectionSource,
ContatoEntity.class, true);
TableUtils.dropTable(connectionSource,
PessoaEntity.class, true);
TableUtils.dropTable(connectionSource,
TipoPessoaEntity.class, true);
onCreate(db, connectionSource);
} catch (SQLException e) {
Log.e(DatabaseHelper.class.getName(), "Can't drop databases", e);
throw new RuntimeException(e);
}
}
@Override
public void close() {
super.close();
}
}Create a class DaoFactory
The DaoFactory is responsible for creating all DAO's we will need as in the following example:
public class DtoFactory extends Application {
private SharedPreferences preferences;
private DatabaseHelper databaseHelper
= null;
private Dao<ContatoEntity, Integer> contatoDAO = null;
private Dao<PessoaEntity,
Integer> pessoaDAO = null;
private
Dao<TipoPessoaEntity, Integer> tpContatoDAO = null;
@Override
public void onCreate() {
super.onCreate();
preferences = PreferenceManager.getDefaultSharedPreferences(this);
databaseHelper = new DatabaseHelper(this);
}
public File getVideosDir() {return videos_dir;}
public SharedPreferences
getPreferences() {return preferences;}
public Dao<ContatoEntity,
Integer> getContatoDao() throws SQLException {
if (contatoDAO == null) {
contatoDAO = databaseHelper.getDao(ContatoEntity.class);
}
return contatoDAO;
}
public Dao<PessoaEntity, Integer>
getPessoaDao() throws SQLException {
if (pessoaDAO == null) {
pessoaDAO = databaseHelper.getDao(PessoaEntity.class);
}
return pessoaDAO;
}
public Dao<TipoPessoaEntity,
Integer> getTpPessoaDao() throws SQLException {
if (tpContatoDAO == null) {
tpContatoDAO = databaseHelper.getDao(TipoPessoaEntity.class);
}
return tpContatoDAO;
}
@Override
public void onTerminate() {
super.onTerminate();
if (databaseHelper != null) {
OpenHelperManager.releaseHelper();
databaseHelper = null;
}
}
}
Using the entities in your Activity as desired.
Warning: The ORMLite framework does not offer a mechanism for insertion of complex objects (classes that contains within itself another class as property). For that we must always keep in mind, that we have to first save the child class and then the parent class, and then combines them. The example below illustrates this problem with a solution. Note: If the class is composed of several hierarchias of composite properties, the only solution i found is to do a recursive method that dives into it and runs backwards inserting and linking the children to its parents. The followed annotation must be used be used by all child classes: (remember the annotation of pessoaEntitiy above? if not look at it now! ;-)@DatabaseField(foreign = true,foreignAutoCreate = true,foreignAutoRefresh = true)
This annotation ensures that the complex type (childs) are really saved in the database and not only updated. See the example bellow:
public class MainActivity extends Activity {
private String LOG_TAG = MainActivity.class.getSimpleName();
private DtoFactory dtoFactory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dtoFactory = (DtoFactory) getApplication();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onclick(View view) throws SQLException {
try {
Dao<PessoaEntity,
Integer> pDao = dtoFactory.getPessoaDao();
Dao<TipoPessoaEntity,
Integer> tpDao = dtoFactory.getTpPessoaDao();
switch (view.getId())
{
case R.id.btnInsert:
System.out.println("insert");
TipoPessoaEntity
tpessoa = new TipoPessoaEntity();
tpessoa.id
= new
Random().nextInt(100);
tpessoa.descricao = "descricao_" + System.currentTimeMillis();
tpDao.create(tpessoa);
PessoaEntity pe1
= new
PessoaEntity();
pe1.id = new
Random().nextInt(100);
pe1.nome = "TestName";
pe1.tpPessoa = tpessoa;
pDao.create(pe1);
break;
case R.id.btnUpdate:
System.out.println("update");
break;
case R.id.btnSelect:
System.out.println("select: "
+ pDao.countOf());
for (PessoaEntity entity
: pDao.queryForAll()) {
System.out.println(String.format("Id: %d, Nome: %s, Tp: %s", entity.id,
entity.nome,
entity.tpPessoa.descricao));
Log.d(LOG_TAG, String.format("Id: %d, Nome: %s, Tp: %s", entity.id,
entity.nome,
entity.tpPessoa.descricao));
}
break;
case R.id.btnDelete:
System.out.println("delete");
break;
default:
break;
}
} catch (Exception e) {
System.out.println();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
1 Proof of Concept
Copy this xml code into your MainActivity:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp"
tools:context=".MainActivity"
>
<Button
android:id="@+id/btnInsert"
android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="onclick" android:text="Insert"/>
<Button
android:id="@+id/btnUpdate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="onclick" android:text="Update"/>
<Button
android:id="@+id/btnSelect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="onclick" android:text="Select"/>
<Button
android:id="@+id/btnDelete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:onClick="onclick" android:text="Delete"/>
</LinearLayout>
Testing on the Emulator
If everything goes right you should have something like this at this point of the post:Result
😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👇
Be sure to read, it will change your life!
Show your work by Austin Kleon: https://amzn.to/34NVmwx
This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practices: https://amzn.to/30WQSm2
Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv
This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp
Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy
😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO 😱👆