O ORMLite é uma biblioteca eficiente que simplifica a persistência de dados em aplicações Android, mapeando objetos Java para tabelas SQLite. Neste guia, exploraremos como realizar operações fundamentais de banco de dados, aplicar o padrão Singleton para gerenciamento de conexões e otimizar o acesso a objetos de acesso a dados (DAOs).
1. Estrutura da Interface de Usuário
Para interagir com o banco de dados, utilizaremos um layout simples composto por botões que acionam as operações de inserção, consulta, deleção e atualização para diferentes entidades.
<!-- activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<GridLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnCount="2">
<Button android:text="Novo Usuário" android:onClick="onInsertUser" />
<Button android:text="Listar Usuários" android:onClick="onFetchUsers" />
<Button android:text="Remover Usuário" android:onClick="onDeleteUser" />
<Button android:text="Atualizar Usuário" android:onClick="onUpdateUser" />
<Button android:text="Novo Setor" android:onClick="onAddDepartment" />
<Button android:text="Ver Setores" android:onClick="onListDepartments" />
<Button android:text="Novo Colaborador" android:onClick="onAddEmployee" />
<Button android:text="Ver Colaboradores" android:onClick="onListEmployees" />
</GridLayout>
</LinearLayout>
2. Definição das Entidades (Modelos)
As classes de modelo utilizam anotações do ORMLite para definir a estrutura das tabelas e os relacionamentos.
Entidade Usuário
@DatabaseTable(tableName = "usuarios")
public class Usuario implements Serializable {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField(canBeNull = false)
private String login;
@DatabaseField(canBeNull = false)
private String senha;
@DatabaseField(dataType = DataType.DATE)
private Date dataCriacao;
public Usuario() {}
public Usuario(String login, String senha, Date data) {
this.login = login;
this.senha = senha;
this.dataCriacao = data;
}
// Getters e Setters...
}
Entidades com Relacionamento (Setor e Colaborador)
Utilizamos ForeignCollectionField para representar o lado "um" de um relacionamento um-para-muitos.
@DatabaseTable(tableName = "setores")
public class Setor implements Serializable {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField
private String nomeSetor;
@ForeignCollectionField(eager = false)
private ForeignCollection<Colaborador> colaboradores;
// Construtores e métodos omitidos...
}
@DatabaseTable(tableName = "colaboradores")
public class Colaborador implements Serializable {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField
private String nome;
@DatabaseField(columnName = "setor_id", foreign = true, foreignAutoRefresh = true)
private Setor setor;
// Construtores e métodos omitidos...
}
3. Gerenciamento do Banco de Dados (DatabaseHelper)
Implementamos o DatabaseHelper utilizando o padrão Singleton para evitar vazamentos de memória e conflitos de conexão. Além disso, incluímos um cache de DAOs para melhorar a performance.
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DB_NAME = "app_database.db";
private static final int DB_VERSION = 1;
private static DatabaseHelper instance;
private Map<String, Dao> daoCache = new HashMap<>();
private DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
public static synchronized DatabaseHelper getInstance(Context context) {
if (instance == null) {
instance = new DatabaseHelper(context.getApplicationContext());
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase db, ConnectionSource source) {
try {
TableUtils.createTable(source, Usuario.class);
TableUtils.createTable(source, Setor.class);
TableUtils.createTable(source, Colaborador.class);
} catch (SQLException e) {
Log.e("DB", "Erro ao criar tabelas", e);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource source, int oldVer, int newVer) {
try {
TableUtils.dropTable(source, Usuario.class, true);
onCreate(db, source);
} catch (SQLException e) {
Log.e("DB", "Erro no upgrade", e);
}
}
public <D extends Dao<T, ?>, T> D getCachedDao(Class<T> clazz) throws SQLException {
String className = clazz.getSimpleName();
if (!daoCache.containsKey(className)) {
daoCache.put(className, getDao(clazz));
}
return (D) daoCache.get(className);
}
@Override
public void close() {
super.close();
daoCache.clear();
}
}
4. Implementação da Camada DAO
Os DAOs isolam a lógica de persistência da lógica de interface.
public class UsuarioRepository {
private Dao<Usuario, Integer> usuarioDao;
public UsuarioRepository(Context context) {
try {
usuarioDao = DatabaseHelper.getInstance(context).getCachedDao(Usuario.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
public void salvar(Usuario u) throws SQLException {
usuarioDao.create(u);
}
public List<Usuario> buscarTodos() throws SQLException {
return usuarioDao.queryForAll();
}
public void atualizar(Usuario u) throws SQLException {
usuarioDao.update(u);
}
public List<Usuario> buscarPorNome(String termo) throws SQLException {
QueryBuilder<Usuario, Integer> qb = usuarioDao.queryBuilder();
qb.where().like("login", "%" + termo + "%");
return qb.query();
}
}
5. Integração na Activity
Finalmente, conectamos as ações da interface aos repositórios de dados.
public class MainActivity extends Activity {
private UsuarioRepository userRepo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userRepo = new UsuarioRepository(this);
}
public void onInsertUser(View v) {
try {
Usuario novo = new Usuario("dev_user", "pass123", new Date());
userRepo.salvar(novo);
Toast.makeText(this, "Usuário salvo!", Toast.LENGTH_SHORT).show();
} catch (SQLException e) {
Log.e("UI", "Falha ao inserir", e);
}
}
public void onFetchUsers(View v) {
try {
List<Usuario> lista = userRepo.buscarTodos();
for (Usuario u : lista) {
Log.d("DB_RESULT", "ID: " + u.getId() + " - Login: " + u.getLogin());
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}