Database Architecture & Room Configuration
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt
- app/src/main/java/io/github/mojri/hesabyar/data/Entities.kt
- app/src/main/java/io/github/mojri/hesabyar/data/HesabyarRepository.kt
- app/src/main/java/io/github/mojri/hesabyar/di/DatabaseModule.kt
- app/src/main/java/io/github/mojri/hesabyar/data/TypeConverters.kt
- rust/hesabyar-core/README.md
The database system in Hesabyar is built on the Room Persistence Library, providing an abstraction layer over SQLite to manage financial records including transactions, loans, installments, and categories. It is designed with an offline-first approach, ensuring all core functionalities remain operational without internet connectivity. The architecture emphasizes data integrity through complex migrations and security via SQLCipher encryption.
The database serves as the primary source of truth for the application's state, with data flowing through a Repository pattern to the UI. It also maintains parity with a Rust-based core for high-performance financial logic, using shared models and data types.
Sources: README.md, app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:15-22
Core Components and Schema
The database architecture consists of several key entities that represent the financial domain of the application. These entities are managed by Data Access Objects (DAOs) and structured within the AppDatabase class.
Entity Relationship Diagram
The following diagram illustrates the relationships between the primary database entities:
The diagram shows how categories, transactions, loans, and installments are interconnected within the schema.
Sources: app/src/main/java/io/github/mojri/hesabyar/data/Entities.kt:7-145, app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:15-22
Database Entities Table
| Entity | Table Name | Purpose | Primary Fields |
|---|---|---|---|
Category | categories | Defines transaction types (Food, Bills, etc.) | name, key, icon, color, type |
Transaction | transactions | Records income and expenses | type, categoryId, amount, date |
Loan | loans | Tracks debts and credits with persons | personName, type, originalAmount, remainingAmount |
Installment | installments | Manages recurring scheduled payments | title, amount, dueDate, isPaid |
PaymentHistory | payment_history | Logs individual payments made toward loans | loanId, amount, date, notes |
Sources: app/src/main/java/io/github/mojri/hesabyar/data/Entities.kt:7-145
Database Security and Encryption
Hesabyar implements robust security for financial data using SQLCipher to provide full-database encryption (AES-256). The encryption process is managed during database initialization, including a migration path for existing plaintext databases.
Encryption Initialization Flow
This flow ensures that if a user has an older, unencrypted database, it is safely migrated to an encrypted format without data loss.
Sources: app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:135-230
Key Implementation Details
- SQLCipher Integration: The
SupportOpenHelperFactoryis initialized with a passphrase retrieved from aDatabaseKeyManager. - Automatic Migration: The
migratePlaintextToEncryptedIfNeededfunction handles the transition by reading records from a temporary plaintext database and inserting them into a newly created encrypted instance. - Transaction Safety: Data restoration during encryption migration is wrapped in
runInTransactionto ensure atomicity.
Sources: app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:135-154, app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:187-208
Migration Strategy
The project maintains a rigorous migration history to handle schema changes and data corrections. The current database version is 4.
Version History and Migrations
| Migration | Purpose | Key Actions |
|---|---|---|
| 1 → 2 | Currency Unit Standardization | Converted amounts to Rials (multiplied by 1000). Recreated all major tables. |
| 2 → 3 | Category System Overhaul | Introduced categories table. Replaced string-based categories in transactions with categoryId. |
| 3 → 4 | Data Inflation Correction | Corrected an error from MIGRATION_1_2 where amounts were inflated by 100x too much (Correct factor: 10 for Toman to Rial). |
Sources: app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:32-133
Complex Data Handling
In MIGRATION_2_3, a mapping logic was implemented to transition existing string categories to the new relational structure:
db.execSQL("""
INSERT INTO transactions_new (...)
SELECT t.id, t.type,
CASE t.category
WHEN 'Food' THEN (SELECT id FROM categories WHERE key = 'Food' LIMIT 1)
...
ELSE (SELECT id FROM categories WHERE key = 'Other' LIMIT 1)
END,
t.amount, ...
FROM transactions t
""")
Sources: app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:105-131
Data Access and Dependency Injection
The database utilizes Hilt for Dependency Injection, providing singletons for the database instance and individual DAOs throughout the application.
Dependency Injection Structure
The DatabaseModule ensures that only one instance of the database and its DAOs exist during the application lifecycle.
Sources: app/src/main/java/io/github/mojri/hesabyar/di/DatabaseModule.kt:17-43
Repository Interaction
The HesabyarRepository orchestrates high-level operations, often involving multiple DAOs within a single transaction to maintain consistency. For example, adding a payment to a loan involves updating the Loan entity, inserting a PaymentHistory record, and creating a corresponding Transaction.
Sources: app/src/main/java/io/github/mojri/hesabyar/data/HesabyarRepository.kt:66-103
Summary
The database architecture of Hesabyar is a sophisticated implementation of Room that prioritizes security and data consistency. By utilizing SQLCipher for encryption and a centralized Repository for complex business logic, the system provides a reliable foundation for personal finance management. The inclusion of a shared native core (Rust) and standard i64 (Long) types for financial amounts ensures high performance and accuracy across the platform.
Sources: rust/hesabyar-core/README.md, app/src/main/java/io/github/mojri/hesabyar/data/AppDatabase.kt:15-22