🎯 Exemplos recomendados
Balanced sample collections from various categories for you to explore
Exemplos de Banco de Dados Android Kotlin
Exemplos de banco de dados Android Kotlin incluindo conexão SQLite, execução de consultas SQL e processamento de transações
💻 Conexão SQLite kotlin
🟡 intermediate
⭐⭐⭐⭐
Conectar ao banco de dados SQLite, criar assistente de banco de dados e gerenciar ciclo de vida do banco de dados
⏱️ 30 min
🏷️ kotlin, android, database, sqlite
Prerequisites:
Intermediate Kotlin, Android SDK, SQL basics
// Android Kotlin SQLite Connection Examples
// Using Android SQLiteOpenHelper and SQLite API
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.database.sqlite.SQLiteDatabase.CursorFactory
import android.content.ContentValues
import android.database.Cursor
// 1. Database Helper Class
class UserDatabaseHelper(
context: Context,
databaseName: String = "UserDatabase.db",
factory: CursorFactory? = null,
version: Int = 1
) : SQLiteOpenHelper(context, databaseName, factory, version) {
companion object {
private const val DATABASE_NAME = "UserDatabase.db"
private const val DATABASE_VERSION = 1
// Table names
private const val TABLE_USERS = "users"
private const val TABLE_PROFILES = "profiles"
// Users table columns
private const val COLUMN_USER_ID = "user_id"
private const val COLUMN_USERNAME = "username"
private const val COLUMN_EMAIL = "email"
private const val COLUMN_PASSWORD = "password"
private const val COLUMN_CREATED_AT = "created_at"
// Profiles table columns
private const val COLUMN_PROFILE_ID = "profile_id"
private const val COLUMN_USER_ID_FK = "user_id"
private const val COLUMN_FULL_NAME = "full_name"
private const val COLUMN_BIO = "bio"
private const val COLUMN_AGE = "age"
}
override fun onCreate(db: SQLiteDatabase) {
// Create users table
val createUsersTable = """
CREATE TABLE $TABLE_USERS (
$COLUMN_USER_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$COLUMN_USERNAME TEXT UNIQUE NOT NULL,
$COLUMN_EMAIL TEXT UNIQUE NOT NULL,
$COLUMN_PASSWORD TEXT NOT NULL,
$COLUMN_CREATED_AT DATETIME DEFAULT CURRENT_TIMESTAMP
)
""".trimIndent()
// Create profiles table
val createProfilesTable = """
CREATE TABLE $TABLE_PROFILES (
$COLUMN_PROFILE_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$COLUMN_USER_ID_FK INTEGER,
$COLUMN_FULL_NAME TEXT,
$COLUMN_BIO TEXT,
$COLUMN_AGE INTEGER,
FOREIGN KEY($COLUMN_USER_ID_FK) REFERENCES $TABLE_USERS($COLUMN_USER_ID)
ON DELETE CASCADE
)
""".trimIndent()
// Create indexes
val createUsernameIndex = """
CREATE INDEX idx_username ON $TABLE_USERS($COLUMN_USERNAME)
""".trimIndent()
val createEmailIndex = """
CREATE INDEX idx_email ON $TABLE_USERS($COLUMN_EMAIL)
""".trimIndent()
db.execSQL(createUsersTable)
db.execSQL(createProfilesTable)
db.execSQL(createUsernameIndex)
db.execSQL(createEmailIndex)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// Handle database upgrades
when (oldVersion) {
1 -> {
// Upgrade from version 1 to 2
upgradeToVersion2(db)
}
2 -> {
// Upgrade from version 2 to 3
upgradeToVersion3(db)
}
// Add more upgrade paths as needed
}
}
private fun upgradeToVersion2(db: SQLiteDatabase) {
// Example: Add new column
db.execSQL("ALTER TABLE $TABLE_USERS ADD COLUMN phone TEXT")
}
private fun upgradeToVersion3(db: SQLiteDatabase) {
// Example: Create new table
db.execSQL("""
CREATE TABLE user_settings (
setting_id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER,
setting_key TEXT,
setting_value TEXT,
FOREIGN KEY(user_id) REFERENCES users(user_id)
)
""".trimIndent())
}
override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// Handle database downgrades
// In production, you might want to backup data first
onConfigure(db)
onCreate(db)
}
override fun onConfigure(db: SQLiteDatabase) {
super.onConfigure(db)
// Enable foreign key constraints
db.setForeignKeyConstraintsEnabled(true)
// Enable Write-Ahead Logging (WAL) for better concurrency
// Note: Available on API 16+
// db.enableWriteAheadLogging()
}
override fun onOpen(db: SQLiteDatabase) {
super.onOpen(db)
// Perform any operations needed when database is opened
}
}
// 2. Database Connection Manager
class DatabaseConnectionManager(private val context: Context) {
private var dbHelper: UserDatabaseHelper? = null
private var database: SQLiteDatabase? = null
// Open database for reading
fun openReadable(): SQLiteDatabase? {
if (database == null || database?.isOpen == false) {
dbHelper = UserDatabaseHelper(context)
database = dbHelper?.readableDatabase
}
return database
}
// Open database for writing
fun openWritable(): SQLiteDatabase? {
if (database == null || database?.isOpen == false) {
dbHelper = UserDatabaseHelper(context)
database = dbHelper?.writableDatabase
}
return database
}
// Close database connection
fun close() {
dbHelper?.close()
database = null
dbHelper = null
}
// Check if database is open
fun isOpen(): Boolean {
return database?.isOpen == true
}
// Get database path
fun getDatabasePath(): String {
return context.getDatabasePath("UserDatabase.db").absolutePath
}
// Get database size
fun getDatabaseSize(): Long {
val file = context.getDatabasePath("UserDatabase.db")
return if (file.exists()) file.length() else 0L
}
// Check if database exists
fun databaseExists(): Boolean {
val file = context.getDatabasePath("UserDatabase.db")
return file.exists()
}
// Delete database
fun deleteDatabase(): Boolean {
close()
return context.deleteDatabase("UserDatabase.db")
}
}
// 3. Database Configuration
class DatabaseConfig(private val context: Context) {
// Configure database with specific settings
fun configureDatabase(): UserDatabaseHelper {
val helper = UserDatabaseHelper(context)
// Get writable database to apply configurations
val db = helper.writableDatabase
// Set database locale
db.setLocale(java.util.Locale.getDefault())
// Set maximum database size (in bytes)
val maxSize = 10 * 1024 * 1024 // 10 MB
db.setMaxSqlCacheSize(maxSize)
return helper
}
// Create in-memory database for testing
fun createInMemoryDatabase(): SQLiteDatabase {
return SQLiteDatabase.create(
SQLiteDatabase.OpenParams.Builder().build()
)
}
// Create database with specific configuration
fun createCustomDatabase(
name: String,
version: Int,
enableForeignKeys: Boolean = true,
enableWAL: Boolean = true
): UserDatabaseHelper {
val helper = UserDatabaseHelper(context, name, null, version)
val db = helper.writableDatabase
db.setForeignKeyConstraintsEnabled(enableForeignKeys)
if (enableWAL) {
// db.enableWriteAheadLogging()
}
return helper
}
}
// 4. Database Lifecycle Management
class DatabaseLifecycleManager(private val context: Context) {
private val connectionManagers = mutableListOf<DatabaseConnectionManager>()
// Register a connection manager
fun registerConnection(manager: DatabaseConnectionManager) {
connectionManagers.add(manager)
}
// Close all connections
fun closeAllConnections() {
connectionManagers.forEach { it.close() }
connectionManagers.clear()
}
// Backup database
fun backupDatabase(backupPath: String): Boolean {
val dbFile = context.getDatabasePath("UserDatabase.db")
val backupFile = java.io.File(backupPath)
return try {
java.io.FileInputStream(dbFile).use { input ->
java.io.FileOutputStream(backupFile).use { output ->
input.copyTo(output)
}
}
true
} catch (e: Exception) {
println("Backup failed: ${e.message}")
false
}
}
// Restore database
fun restoreDatabase(backupPath: String): Boolean {
val backupFile = java.io.File(backupPath)
val dbFile = context.getDatabasePath("UserDatabase.db")
return try {
// Close existing connection
closeAllConnections()
java.io.FileInputStream(backupFile).use { input ->
java.io.FileOutputStream(dbFile).use { output ->
input.copyTo(output)
}
}
true
} catch (e: Exception) {
println("Restore failed: ${e.message}")
false
}
}
// Vacuum database (reclaim space)
fun vacuumDatabase(): Boolean {
val manager = DatabaseConnectionManager(context)
val db = manager.openWritable()
return try {
db?.execSQL("VACUUM")
true
} catch (e: Exception) {
println("Vacuum failed: ${e.message}")
false
} finally {
manager.close()
}
}
// Analyze database (update statistics)
fun analyzeDatabase(): Boolean {
val manager = DatabaseConnectionManager(context)
val db = manager.openWritable()
return try {
db?.execSQL("ANALYZE")
true
} catch (e: Exception) {
println("Analyze failed: ${e.message}")
false
} finally {
manager.close()
}
}
}
// 5. Database Information
class DatabaseInfo(private val context: Context) {
// Get database version
fun getDatabaseVersion(): Int {
val helper = UserDatabaseHelper(context)
return helper.readableDatabase.version
}
// Get database page size
fun getDatabasePageSize(): Int {
val manager = DatabaseConnectionManager(context)
val db = manager.openReadable()
var pageSize = 0
val cursor = db?.rawQuery("PRAGMA page_size", null)
cursor?.use {
if (it.moveToFirst()) {
pageSize = it.getInt(0)
}
}
manager.close()
return pageSize
}
// Get database encoding
fun getDatabaseEncoding(): String {
val manager = DatabaseConnectionManager(context)
val db = manager.openReadable()
var encoding = ""
val cursor = db?.rawQuery("PRAGMA encoding", null)
cursor?.use {
if (it.moveToFirst()) {
encoding = it.getString(0)
}
}
manager.close()
return encoding
}
// List all tables
fun listTables(): List<String> {
val manager = DatabaseConnectionManager(context)
val db = manager.openReadable()
val tables = mutableListOf<String>()
val cursor = db?.rawQuery(
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name",
null
)
cursor?.use {
while (it.moveToNext()) {
tables.add(it.getString(0))
}
}
manager.close()
return tables
}
// Get table info
fun getTableInfo(tableName: String): List<ColumnInfo> {
val manager = DatabaseConnectionManager(context)
val db = manager.openReadable()
val columns = mutableListOf<ColumnInfo>()
val cursor = db?.rawQuery("PRAGMA table_info($tableName)", null)
cursor?.use {
val indexName = it.getColumnIndex("name")
val indexType = it.getColumnIndex("type")
val indexNotNull = it.getColumnIndex("notnull")
val indexDefault = it.getColumnIndex("dflt_value")
while (it.moveToNext()) {
columns.add(
ColumnInfo(
name = it.getString(indexName),
type = it.getString(indexType),
notNull = it.getInt(indexNotNull) == 1,
defaultValue = it.getString(indexDefault)
)
)
}
}
manager.close()
return columns
}
// Get table count
fun getTableCount(tableName: String): Int {
val manager = DatabaseConnectionManager(context)
val db = manager.openReadable()
var count = 0
val cursor = db?.rawQuery("SELECT COUNT(*) FROM $tableName", null)
cursor?.use {
if (it.moveToFirst()) {
count = it.getInt(0)
}
}
manager.close()
return count
}
}
// Column Info Data Class
data class ColumnInfo(
val name: String,
val type: String,
val notNull: Boolean,
val defaultValue: String?
)
// Main demonstration
fun demonstrateSQLiteConnection(context: Context) {
println("=== Android Kotlin SQLite Connection Examples ===\n")
// 1. Create database helper
println("--- 1. Create Database Helper ---")
val dbHelper = UserDatabaseHelper(context)
println("Database helper created")
println("Database name: ${UserDatabaseHelper.DATABASE_NAME}")
println("Database version: ${UserDatabaseHelper.DATABASE_VERSION}")
// 2. Connection manager
println("\n--- 2. Connection Manager ---")
val connManager = DatabaseConnectionManager(context)
// Open for reading
val readDb = connManager.openReadable()
println("Database opened for reading: ${readDb != null}")
// Open for writing
val writeDb = connManager.openWritable()
println("Database opened for writing: ${writeDb != null}")
println("Is database open: ${connManager.isOpen()}")
println("Database exists: ${connManager.databaseExists()}")
println("Database path: ${connManager.getDatabasePath()}")
println("Database size: ${connManager.getDatabaseSize()} bytes")
// 3. Database configuration
println("\n--- 3. Database Configuration ---")
val config = DatabaseConfig(context)
val configuredHelper = config.configureDatabase()
println("Database configured")
// 4. Database information
println("\n--- 4. Database Information ---")
val dbInfo = DatabaseInfo(context)
println("Database version: ${dbInfo.getDatabaseVersion()}")
println("Page size: ${dbInfo.getDatabasePageSize()}")
println("Encoding: ${dbInfo.getDatabaseEncoding()}")
println("\nTables:")
val tables = dbInfo.listTables()
tables.forEach { println(" - $it") }
if (tables.isNotEmpty()) {
println("\nTable info for '${tables[0]}':")
val columns = dbInfo.getTableInfo(tables[0])
columns.forEach { col ->
println(" - ${col.name}: ${col.type} ${if (col.notNull) "NOT NULL" else ""}")
}
println("\nRow count: ${dbInfo.getTableCount(tables[0])}")
}
// 5. Lifecycle management
println("\n--- 5. Lifecycle Management ---")
val lifecycleManager = DatabaseLifecycleManager(context)
lifecycleManager.registerConnection(connManager)
// Note: Backup operations need appropriate storage permissions
// val backupSuccess = lifecycleManager.backupDatabase("/path/to/backup.db")
// println("Backup successful: $backupSuccess")
// 6. Cleanup
println("\n--- 6. Cleanup ---")
connManager.close()
println("Database connection closed")
println("\n=== All SQLite Connection Examples Completed ===")
}
💻 Executar Consultas SQL kotlin
🟡 intermediate
⭐⭐⭐⭐
Executar consultas SELECT, INSERT, UPDATE, DELETE e usar SQL bruto com instruções preparadas
⏱️ 35 min
🏷️ kotlin, android, database, sql
Prerequisites:
Intermediate Kotlin, Android SDK, SQL knowledge
// Android Kotlin Execute SQL Queries Examples
// Using SQLiteDatabase and ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.content.ContentValues
import android.database.Cursor
// Database helper (same as connection example)
class UserDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "UserDatabase.db", null, 1) {
companion object {
private const val TABLE_USERS = "users"
private const val COLUMN_ID = "user_id"
private const val COLUMN_USERNAME = "username"
private const val COLUMN_EMAIL = "email"
private const val COLUMN_AGE = "age"
private const val COLUMN_SCORE = "score"
}
override fun onCreate(db: SQLiteDatabase) {
val createTable = """
CREATE TABLE $TABLE_USERS (
$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$COLUMN_USERNAME TEXT NOT NULL,
$COLUMN_EMAIL TEXT NOT NULL,
$COLUMN_AGE INTEGER DEFAULT 0,
$COLUMN_SCORE INTEGER DEFAULT 0
)
""".trimIndent()
db.execSQL(createTable)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
}
// 1. INSERT Operations
class InsertOperations(private val dbHelper: UserDatabaseHelper) {
// Insert single row using ContentValues
fun insertUser(username: String, email: String, age: Int): Long {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_USERNAME, username)
put(COLUMN_EMAIL, email)
put(COLUMN_AGE, age)
put(COLUMN_SCORE, 0)
}
val rowId = db.insert(TABLE_USERS, null, values)
println("Inserted user with row ID: $rowId")
return rowId
}
// Insert multiple rows using transaction
fun insertMultipleUsers(users: List<User>): Int {
val db = dbHelper.writableDatabase
var count = 0
db.beginTransaction()
try {
for (user in users) {
val values = ContentValues().apply {
put(COLUMN_USERNAME, user.username)
put(COLUMN_EMAIL, user.email)
put(COLUMN_AGE, user.age)
}
val rowId = db.insert(TABLE_USERS, null, values)
if (rowId > 0) count++
}
db.setTransactionSuccessful()
} finally {
db.endTransaction()
}
println("Inserted $count users")
return count
}
// Insert using raw SQL
fun insertUserRawSQL(username: String, email: String, age: Int): Boolean {
val db = dbHelper.writableDatabase
val sql = "INSERT INTO $TABLE_USERS ($COLUMN_USERNAME, $COLUMN_EMAIL, $COLUMN_AGE) VALUES (?, ?, ?)"
try {
db.execSQL(sql, arrayOf(username, email, age))
println("Inserted user using raw SQL: $username")
return true
} catch (e: Exception) {
println("Error inserting user: ${e.message}")
return false
}
}
// Insert or replace (upsert)
fun insertOrReplaceUser(id: Int, username: String, email: String): Long {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_ID, id)
put(COLUMN_USERNAME, username)
put(COLUMN_EMAIL, email)
}
val rowId = db.insertWithOnConflict(
TABLE_USERS,
null,
values,
SQLiteDatabase.CONFLICT_REPLACE
)
println("Inserted or replaced user with row ID: $rowId")
return rowId
}
// Insert with null column handling
fun insertUserWithOptionalFields(
username: String,
email: String?,
age: Int?
): Long {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_USERNAME, username)
put(COLUMN_EMAIL, email)
put(COLUMN_AGE, age)
}
return db.insert(TABLE_USERS, null, values)
}
}
// 2. SELECT Operations
class SelectOperations(private val dbHelper: UserDatabaseHelper) {
// Query all users
fun getAllUsers(): List<User> {
val db = dbHelper.readableDatabase
val users = mutableListOf<User>()
val cursor: Cursor = db.query(
TABLE_USERS,
null, // Select all columns
null, // No WHERE clause
null, // No WHERE arguments
null, // No GROUP BY
null, // No HAVING
"$COLUMN_USERNAME ASC" // Order by username
)
cursor.use {
while (it.moveToNext()) {
users.add(cursorToUser(it))
}
}
println("Retrieved ${users.size} users")
return users
}
// Query with WHERE clause
fun getUsersByAge(minAge: Int): List<User> {
val db = dbHelper.readableDatabase
val users = mutableListOf<User>()
val selection = "$COLUMN_AGE >= ?"
val selectionArgs = arrayOf(minAge.toString())
val cursor = db.query(
TABLE_USERS,
null,
selection,
selectionArgs,
null,
null,
"$COLUMN_AGE DESC"
)
cursor.use {
while (it.moveToNext()) {
users.add(cursorToUser(it))
}
}
return users
}
// Query with multiple conditions
fun getUsersWithConditions(
minAge: Int,
maxScore: Int,
usernamePattern: String
): List<User> {
val db = dbHelper.readableDatabase
val users = mutableListOf<User>()
val selection = "$COLUMN_AGE >= ? AND $COLUMN_SCORE <= ? AND $COLUMN_USERNAME LIKE ?"
val selectionArgs = arrayOf(minAge.toString(), maxScore.toString(), "$usernamePattern%")
val cursor = db.query(
TABLE_USERS,
null,
selection,
selectionArgs,
null,
null,
null
)
cursor.use {
while (it.moveToNext()) {
users.add(cursorToUser(it))
}
}
return users
}
// Query specific columns
fun getUsernamesOnly(): List<String> {
val db = dbHelper.readableDatabase
val usernames = mutableListOf<String>()
val columns = arrayOf(COLUMN_USERNAME)
val cursor = db.query(TABLE_USERS, columns, null, null, null, null, null)
cursor.use {
while (it.moveToNext()) {
usernames.add(it.getString(0))
}
}
return usernames
}
// Query with raw SQL
fun getUsersRawSQL(minAge: Int, maxAge: Int): List<User> {
val db = dbHelper.readableDatabase
val users = mutableListOf<User>()
val sql = "SELECT * FROM $TABLE_USERS WHERE $COLUMN_AGE BETWEEN ? AND ? ORDER BY $COLUMN_USERNAME"
val cursor = db.rawQuery(sql, arrayOf(minAge.toString(), maxAge.toString()))
cursor.use {
while (it.moveToNext()) {
users.add(cursorToUser(it))
}
}
return users
}
// Query single user
fun getUserById(id: Int): User? {
val db = dbHelper.readableDatabase
val selection = "$COLUMN_ID = ?"
val selectionArgs = arrayOf(id.toString())
val cursor = db.query(
TABLE_USERS,
null,
selection,
selectionArgs,
null,
null,
null
)
cursor.use {
if (it.moveToFirst()) {
return cursorToUser(it)
}
}
return null
}
// Count query
fun getUserCount(): Int {
val db = dbHelper.readableDatabase
val cursor = db.query(
TABLE_USERS,
arrayOf("COUNT(*)"),
null,
null,
null,
null,
null
)
cursor.use {
if (it.moveToFirst()) {
return it.getInt(0)
}
}
return 0
}
// Helper: Convert cursor to User object
private fun cursorToUser(cursor: Cursor): User {
return User(
id = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_ID)),
username = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_USERNAME)),
email = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_EMAIL)),
age = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_AGE)),
score = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_SCORE))
)
}
}
// 3. UPDATE Operations
class UpdateOperations(private val dbHelper: UserDatabaseHelper) {
// Update single field
fun updateUserEmail(userId: Int, newEmail: String): Int {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_EMAIL, newEmail)
}
val whereClause = "$COLUMN_ID = ?"
val whereArgs = arrayOf(userId.toString())
val rowsAffected = db.update(TABLE_USERS, values, whereClause, whereArgs)
println("Updated email for user $userId: $rowsAffected rows affected")
return rowsAffected
}
// Update multiple fields
fun updateUser(userId: Int, username: String, email: String, age: Int): Int {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_USERNAME, username)
put(COLUMN_EMAIL, email)
put(COLUMN_AGE, age)
}
val whereClause = "$COLUMN_ID = ?"
val whereArgs = arrayOf(userId.toString())
return db.update(TABLE_USERS, values, whereClause, whereArgs)
}
// Update with expression
fun incrementUserScore(userId: Int, increment: Int): Int {
val db = dbHelper.writableDatabase
val sql = "UPDATE $TABLE_USERS SET $COLUMN_SCORE = $COLUMN_SCORE + ? WHERE $COLUMN_ID = ?"
db.execSQL(sql, arrayOf(increment.toString(), userId.toString()))
// Return rows affected (need separate query)
return 1
}
// Update multiple rows
fun updateAllScoresByAge(minAge: Int, bonusScore: Int): Int {
val db = dbHelper.writableDatabase
val values = ContentValues().apply {
put(COLUMN_SCORE, bonusScore)
}
val whereClause = "$COLUMN_AGE >= ?"
val whereArgs = arrayOf(minAge.toString())
val rowsAffected = db.update(TABLE_USERS, values, whereClause, whereArgs)
println("Updated scores for ${rowsAffected} users aged $minAge and above")
return rowsAffected
}
// Update using raw SQL
fun updateUserRawSQL(userId: Int, newUsername: String): Boolean {
val db = dbHelper.writableDatabase
try {
val sql = "UPDATE $TABLE_USERS SET $COLUMN_USERNAME = ? WHERE $COLUMN_ID = ?"
db.execSQL(sql, arrayOf(newUsername, userId.toString()))
return true
} catch (e: Exception) {
println("Error updating user: ${e.message}")
return false
}
}
}
// 4. DELETE Operations
class DeleteOperations(private val dbHelper: UserDatabaseHelper) {
// Delete single row
fun deleteUserById(userId: Int): Int {
val db = dbHelper.writableDatabase
val whereClause = "$COLUMN_ID = ?"
val whereArgs = arrayOf(userId.toString())
val rowsDeleted = db.delete(TABLE_USERS, whereClause, whereArgs)
println("Deleted user $userId: $rowsDeleted rows deleted")
return rowsDeleted
}
// Delete with condition
fun deleteUsersByAge(maxAge: Int): Int {
val db = dbHelper.writableDatabase
val whereClause = "$COLUMN_AGE < ?"
val whereArgs = arrayOf(maxAge.toString())
val rowsDeleted = db.delete(TABLE_USERS, whereClause, whereArgs)
println("Deleted $rowsDeleted users under age $maxAge")
return rowsDeleted
}
// Delete with multiple conditions
fun deleteUsersByScoreRange(minScore: Int, maxScore: Int): Int {
val db = dbHelper.writableDatabase
val whereClause = "$COLUMN_SCORE BETWEEN ? AND ?"
val whereArgs = arrayOf(minScore.toString(), maxScore.toString())
return db.delete(TABLE_USERS, whereClause, whereArgs)
}
// Delete all rows
fun deleteAllUsers(): Int {
val db = dbHelper.writableDatabase
val rowsDeleted = db.delete(TABLE_USERS, null, null)
println("Deleted all users: $rowsDeleted rows deleted")
return rowsDeleted
}
// Delete using raw SQL
fun deleteUsersRawSQL(usernamePattern: String): Int {
val db = dbHelper.writableDatabase
val sql = "DELETE FROM $TABLE_USERS WHERE $COLUMN_USERNAME LIKE ?"
db.execSQL(sql, arrayOf("$usernamePattern%"))
// Get count (simplified)
return 1
}
}
// 5. Prepared Statements
class PreparedStatements(private val dbHelper: UserDatabaseHelper) {
// Insert with parameters
fun insertUserPrepared(username: String, email: String, age: Int): Long {
val db = dbHelper.writableDatabase
val sql = "INSERT INTO $TABLE_USERS ($COLUMN_USERNAME, $COLUMN_EMAIL, $COLUMN_AGE) VALUES (?, ?, ?)"
val stmt = db.compileStatement(sql)
stmt.clearBindings()
stmt.bindString(1, username)
stmt.bindString(2, email)
stmt.bindLong(3, age.toLong())
val rowId = stmt.executeInsert()
stmt.close()
return rowId
}
// Query with parameters
fun findUsersPrepared(ageMin: Int, ageMax: Int): Cursor? {
val db = dbHelper.readableDatabase
val sql = """
SELECT * FROM $TABLE_USERS
WHERE $COLUMN_AGE BETWEEN ? AND ?
ORDER BY $COLUMN_USERNAME
""".trimIndent()
return db.rawQuery(sql, arrayOf(ageMin.toString(), ageMax.toString()))
}
}
// User data class
data class User(
val id: Int = 0,
val username: String,
val email: String,
val age: Int = 0,
val score: Int = 0
)
// Main demonstration
fun demonstrateExecuteSQLQueries(context: Context) {
println("=== Android Kotlin Execute SQL Queries Examples ===\n")
val dbHelper = UserDatabaseHelper(context)
val db = dbHelper.writableDatabase
// 1. INSERT examples
println("--- 1. INSERT Operations ---")
val insertOps = InsertOperations(dbHelper)
val id1 = insertOps.insertUser("alice", "[email protected]", 25)
val id2 = insertOps.insertUser("bob", "[email protected]", 30)
val id3 = insertOps.insertUser("charlie", "[email protected]", 28)
insertOps.insertUserRawSQL("diana", "[email protected]", 22)
val users = listOf(
User(0, "eve", "[email protected]", 26),
User(0, "frank", "[email protected]", 35)
)
insertOps.insertMultipleUsers(users)
// 2. SELECT examples
println("\n--- 2. SELECT Operations ---")
val selectOps = SelectOperations(dbHelper)
val allUsers = selectOps.getAllUsers()
println("All users (${allUsers.size}):")
allUsers.take(3).forEach { println(" - ${it.id}: ${it.username}, ${it.email}, age ${it.age}") }
val usersOver25 = selectOps.getUsersByAge(25)
println("\nUsers aged 25+: ${usersOver25.size}")
val user = selectOps.getUserById(id1.toInt())
println("\nUser by ID $id1: ${user?.username}")
val count = selectOps.getUserCount()
println("\nTotal user count: $count")
// 3. UPDATE examples
println("\n--- 3. UPDATE Operations ---")
val updateOps = UpdateOperations(dbHelper)
updateOps.updateUserEmail(id1.toInt(), "[email protected]")
updateOps.incrementUserScore(id2.toInt(), 10)
updateOps.updateAllScoresByAge(30, 50)
// 4. DELETE examples
println("\n--- 4. DELETE Operations ---")
val deleteOps = DeleteOperations(dbHelper)
deleteOps.deleteUserById(id3.toInt())
deleteOps.deleteUsersByAge(21)
// 5. Prepared statements
println("\n--- 5. Prepared Statements ---")
val prepStmt = PreparedStatements(dbHelper)
val prepId = prepStmt.insertUserPrepared("grace", "[email protected]", 29)
println("Inserted with prepared statement: $prepId")
// Cleanup
dbHelper.close()
println("\nDatabase cleaned up")
println("\n=== All Execute SQL Queries Examples Completed ===")
}
💻 Processamento de Transações kotlin
🔴 complex
⭐⭐⭐⭐⭐
Manipular transações de banco de dados com commit, rollback e tratamento de erros
⏱️ 40 min
🏷️ kotlin, android, database, transactions
Prerequisites:
Advanced Kotlin, Android SDK, SQL transactions
// Android Kotlin Transaction Processing Examples
// Using SQLiteDatabase transactions
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.content.ContentValues
import android.database.Cursor
// Database helper
class BankDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "BankDatabase.db", null, 1) {
companion object {
private const val TABLE_ACCOUNTS = "accounts"
private const val TABLE_TRANSACTIONS = "transactions"
private const val COLUMN_ACCOUNT_ID = "account_id"
private const val COLUMN_ACCOUNT_NAME = "account_name"
private const val COLUMN_BALANCE = "balance"
private const val COLUMN_TX_ID = "tx_id"
private const val COLUMN_FROM_ACCOUNT = "from_account"
private const val COLUMN_TO_ACCOUNT = "to_account"
private const val COLUMN_AMOUNT = "amount"
private const val COLUMN_TX_DATE = "tx_date"
}
override fun onCreate(db: SQLiteDatabase) {
// Create accounts table
db.execSQL("""
CREATE TABLE $TABLE_ACCOUNTS (
$COLUMN_ACCOUNT_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$COLUMN_ACCOUNT_NAME TEXT UNIQUE NOT NULL,
$COLUMN_BALANCE REAL DEFAULT 0.0 CHECK($COLUMN_BALANCE >= 0)
)
""".trimIndent())
// Create transactions table
db.execSQL("""
CREATE TABLE $TABLE_TRANSACTIONS (
$COLUMN_TX_ID INTEGER PRIMARY KEY AUTOINCREMENT,
$COLUMN_FROM_ACCOUNT INTEGER,
$COLUMN_TO_ACCOUNT INTEGER,
$COLUMN_AMOUNT REAL,
$COLUMN_TX_DATE DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY($COLUMN_FROM_ACCOUNT) REFERENCES $TABLE_ACCOUNTS($COLUMN_ACCOUNT_ID),
FOREIGN KEY($COLUMN_TO_ACCOUNT) REFERENCES $TABLE_ACCOUNTS($COLUMN_ACCOUNT_ID)
)
""".trimIndent())
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
}
// 1. Basic Transaction
class BasicTransaction(private val dbHelper: BankDatabaseHelper) {
// Simple transaction with multiple inserts
fun performBatchInsert(accounts: List<Account>): Boolean {
val db = dbHelper.writableDatabase
db.beginTransaction()
try {
for (account in accounts) {
val values = ContentValues().apply {
put(COLUMN_ACCOUNT_NAME, account.name)
put(COLUMN_BALANCE, account.balance)
}
db.insert(TABLE_ACCOUNTS, null, values)
}
// Mark transaction as successful
db.setTransactionSuccessful()
println("Batch insert completed: ${accounts.size} accounts")
return true
} catch (e: Exception) {
println("Batch insert failed: ${e.message}")
return false
} finally {
db.endTransaction()
}
}
// Transaction with explicit control
fun transferFundsBasic(fromId: Int, toId: Int, amount: Double): Boolean {
val db = dbHelper.writableDatabase
// Start transaction
db.beginTransaction()
try {
// Deduct from source account
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE - ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(amount.toString(), fromId.toString())
)
// Add to destination account
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE + ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(amount.toString(), toId.toString())
)
// Mark as successful
db.setTransactionSuccessful()
println("Transfer completed: $amount from account $fromId to $toId")
return true
} catch (e: Exception) {
println("Transfer failed: ${e.message}")
// Transaction will be rolled back
return false
} finally {
db.endTransaction()
}
}
}
// 2. Transaction with Error Handling
class SafeTransaction(private val dbHelper: BankDatabaseHelper) {
// Transfer with validation and rollback
fun transferFundsSafe(fromId: Int, toId: Int, amount: Double): TransferResult {
val db = dbHelper.writableDatabase
// Validate amount
if (amount <= 0) {
return TransferResult(false, "Amount must be positive")
}
db.beginTransaction()
try {
// Check source account balance
val cursor = db.query(
TABLE_ACCOUNTS,
arrayOf(COLUMN_BALANCE),
"$COLUMN_ACCOUNT_ID = ?",
arrayOf(fromId.toString()),
null, null, null
)
cursor.use {
if (!it.moveToFirst()) {
return TransferResult(false, "Source account not found")
}
val currentBalance = it.getDouble(0)
if (currentBalance < amount) {
return TransferResult(false, "Insufficient funds")
}
}
// Check destination account exists
val destCursor = db.query(
TABLE_ACCOUNTS,
arrayOf(COLUMN_ACCOUNT_ID),
"$COLUMN_ACCOUNT_ID = ?",
arrayOf(toId.toString()),
null, null, null
)
destCursor.use {
if (!it.moveToFirst()) {
return TransferResult(false, "Destination account not found")
}
}
// Perform transfer
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE - ? WHERE $COLUMN_ACCOUNT_ID = ? AND $COLUMN_BALANCE >= ?",
arrayOf(amount.toString(), fromId.toString(), amount.toString())
)
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE + ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(amount.toString(), toId.toString())
)
// Record transaction
val txValues = ContentValues().apply {
put(COLUMN_FROM_ACCOUNT, fromId)
put(COLUMN_TO_ACCOUNT, toId)
put(COLUMN_AMOUNT, amount)
}
db.insert(TABLE_TRANSACTIONS, null, txValues)
// Mark as successful
db.setTransactionSuccessful()
println("Transfer successful: $amount from $fromId to $toId")
return TransferResult(true, "Transfer completed successfully")
} catch (e: Exception) {
println("Transfer failed: ${e.message}")
return TransferResult(false, "Transaction error: ${e.message}")
} finally {
db.endTransaction()
}
}
// Batch operation with partial failure handling
fun batchUpdateBalances(updates: List<BalanceUpdate>): BatchResult {
val db = dbHelper.writableDatabase
val results = mutableListOf<SingleResult>()
db.beginTransaction()
try {
for (update in updates) {
try {
val rows = db.update(
TABLE_ACCOUNTS,
ContentValues().apply { put(COLUMN_BALANCE, update.newBalance) },
"$COLUMN_ACCOUNT_ID = ?",
arrayOf(update.accountId.toString())
)
if (rows > 0) {
results.add(SingleResult(update.accountId, true, null))
} else {
results.add(SingleResult(update.accountId, false, "Account not found"))
}
} catch (e: Exception) {
results.add(SingleResult(update.accountId, false, e.message))
}
}
db.setTransactionSuccessful()
return BatchResult(true, results)
} catch (e: Exception) {
return BatchResult(false, results)
} finally {
db.endTransaction()
}
}
}
// 3. Nested Transactions (Savepoints)
class NestedTransaction(private val dbHelper: BankDatabaseHelper) {
// Transfer using savepoints
fun transferWithSavepoint(fromId: Int, toId: Int, amount: Double): Boolean {
val db = dbHelper.writableDatabase
db.beginTransaction()
try {
// First, deduct from source
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE - ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(amount.toString(), fromId.toString())
)
// Create savepoint
val savepointName = "SP_" + System.currentTimeMillis()
db.execSQL("SAVEPOINT $savepointName")
try {
// Try to add to destination
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = $COLUMN_BALANCE + ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(amount.toString(), toId.toString())
)
// If successful, release savepoint
db.execSQL("RELEASE SAVEPOINT $savepointName")
db.setTransactionSuccessful()
return true
} catch (e: Exception) {
// Rollback to savepoint
db.execSQL("ROLLBACK TO SAVEPOINT $savepointName")
throw e
}
} catch (e: Exception) {
println("Transfer failed: ${e.message}")
return false
} finally {
db.endTransaction()
}
}
}
// 4. Transaction Isolation Levels
class IsolatedTransaction(private val dbHelper: BankDatabaseHelper) {
// Immediate lock (exclusive access)
fun transferWithImmediateLock(fromId: Int, toId: Int, amount: Double): Boolean {
val db = dbHelper.writableDatabase
db.beginTransaction()
try {
// Lock accounts table with immediate lock
db.execSQL("BEGIN IMMEDIATE TRANSACTION")
// Perform transfer operations
// ... transfer logic ...
db.setTransactionSuccessful()
return true
} catch (e: Exception) {
println("Transfer failed: ${e.message}")
return false
} finally {
db.endTransaction()
}
}
// Exclusive lock
fun transferWithExclusiveLock(fromId: Int, toId: Int, amount: Double): Boolean {
val db = dbHelper.writableDatabase
try {
// Lock database exclusively
db.execSQL("BEGIN EXCLUSIVE TRANSACTION")
// Perform transfer operations
// ... transfer logic ...
db.setTransactionSuccessful()
return true
} catch (e: Exception) {
println("Transfer failed: ${e.message}")
return false
} finally {
db.endTransaction()
}
}
}
// 5. Non-Transactional (Exclusive) Operations
class NonTransactionalOperation(private val dbHelper: BankDatabaseHelper) {
// Quick update without transaction overhead
fun quickBalanceUpdate(accountId: Int, newBalance: Double): Boolean {
val db = dbHelper.writableDatabase
try {
// Use execSQL for faster, non-transactional operation
db.execSQL(
"UPDATE $TABLE_ACCOUNTS SET $COLUMN_BALANCE = ? WHERE $COLUMN_ACCOUNT_ID = ?",
arrayOf(newBalance.toString(), accountId.toString())
)
return true
} catch (e: Exception) {
println("Quick update failed: ${e.message}")
return false
}
}
}
// 6. Transaction Monitoring
class TransactionMonitor(private val dbHelper: BankDatabaseHelper) {
// Check if database is in transaction
fun isInTransaction(): Boolean {
val db = dbHelper.readableDatabase
return db.inTransaction()
}
// Perform operation with transaction status logging
fun performWithLogging(operation: () -> Boolean): Boolean {
val db = dbHelper.writableDatabase
println("Transaction status before: ${db.inTransaction()}")
db.beginTransaction()
println("Transaction started")
try {
val result = operation()
if (result) {
db.setTransactionSuccessful()
println("Transaction marked as successful")
}
return result
} finally {
db.endTransaction()
println("Transaction ended. Status: ${db.inTransaction()}")
}
}
}
// Data classes
data class Account(val name: String, val balance: Double)
data class BalanceUpdate(val accountId: Int, val newBalance: Double)
data class TransferResult(val success: Boolean, val message: String)
data class BatchResult(val success: Boolean, val results: List<SingleResult>)
data class SingleResult(val accountId: Int, val success: Boolean, val error: String?)
// Main demonstration
fun demonstrateTransactionProcessing(context: Context) {
println("=== Android Kotlin Transaction Processing Examples ===\n")
val dbHelper = BankDatabaseHelper(context)
// 1. Basic transaction
println("--- 1. Basic Transaction ---")
val basicTx = BasicTransaction(dbHelper)
val accounts = listOf(
Account("Alice", 1000.0),
Account("Bob", 500.0),
Account("Charlie", 750.0)
)
basicTx.performBatchInsert(accounts)
// 2. Safe transaction with validation
println("\n--- 2. Safe Transaction ---")
val safeTx = SafeTransaction(dbHelper)
val result1 = safeTx.transferFundsSafe(1, 2, 200.0)
println("Transfer result: ${result1.success} - ${result1.message}")
val result2 = safeTx.transferFundsSafe(1, 2, 5000.0)
println("Transfer result (excess): ${result2.success} - ${result2.message}")
// 3. Batch operations
println("\n--- 3. Batch Operations ---")
val updates = listOf(
BalanceUpdate(1, 800.0),
BalanceUpdate(2, 700.0),
BalanceUpdate(3, 750.0)
)
val batchResult = safeTx.batchUpdateBalances(updates)
println("Batch result: ${batchResult.success}")
batchResult.results.forEach { r ->
println(" Account ${r.accountId}: ${if (r.success) "Success" else "Failed - ${r.error}"}")
}
// 4. Transaction monitoring
println("\n--- 4. Transaction Monitoring ---")
val monitor = TransactionMonitor(dbHelper)
println("In transaction (before): ${monitor.isInTransaction()}")
monitor.performWithLogging {
val transfer = basicTx.transferFundsBasic(1, 2, 50.0)
transfer
}
println("In transaction (after): ${monitor.isInTransaction()}")
// 5. Non-transactional quick operation
println("\n--- 5. Non-Transactional Quick Operation ---")
val nonTx = NonTransactionalOperation(dbHelper)
nonTx.quickBalanceUpdate(1, 850.0)
println("Quick update completed")
// Cleanup
dbHelper.close()
println("\nDatabase cleaned up")
println("\n=== All Transaction Processing Examples Completed ===")
}