793b3b52fa74f69ce297814f53ff359cc0d4d80a
Simple Persistence for Kotlin
A lightweight, file-based persistence library for Kotlin applications that provides a simple way to store, retrieve, and query objects.
Available on Maven Central
// Gradle Kotlin DSL
implementation("nl.astraeus:simple-persistence-kotlin:1.1.5")
// Gradle Groovy DSL
implementation 'nl.astraeus:simple-persistence-kotlin:1.1.5'
<!-- Maven -->
<dependency>
<groupId>nl.astraeus</groupId>
<artifactId>simple-persistence-kotlin</artifactId>
<version>1.1.5</version>
</dependency>
Features
- Simple and intuitive API for persisting Kotlin objects
- Transaction support with ACID properties
- Optimistic locking to handle concurrent modifications
- Flexible indexing for efficient querying
- Object references and collections handling
- Encryption support for sensitive data
- Snapshot and transaction log capabilities
- File-based storage with automatic cleanup
Quick Start
Define your model
class Person(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val age: Int,
company: Company? = null
) : Persistable, Cloneable {
var company: Company? by nullableReference(company)
companion object {
private const val serialVersionUID: Long = 1L
}
}
class Company(
override var id: Long = 0,
override var version: Long = 0,
val name: String
) : Persistable, Cloneable {
val persons: MutableCollection<Person> = referenceCollection()
companion object {
private const val serialVersionUID: Long = 1L
}
}
Initialize the persistence manager
val persistent = Persistent(
directory = File("data", "my-app"),
indexes = arrayOf(
index<Person>("name") { p -> (p as? Person)?.name ?: "" },
index<Person>("age") { p -> (p as? Person)?.age ?: -1 },
index<Company>("name") { p -> (p as? Company)?.name ?: "" }
)
)
Perform CRUD operations
// Create or update
persistent.transaction {
val person = Person(
id = 1L,
name = "John Doe",
age = 30
)
val company = Company(
id = 1L,
name = "ACME Inc."
)
person.company = company
company.persons.add(person)
store(person)
store(company)
}
// Read
persistent.query {
val person = find<Person>(1L)
println("Found person: $person")
// Query by index
val persons: List<Person> = findByIndex("age", 30)
// Search with predicate
val results = search(Person::class) { p -> p.name.startsWith("John") }
}
// Delete
persistent.transaction {
val person = find<Person>(1L)
if (person != null) {
delete(person)
}
}
How it works
- In-memory model: Your objects live in memory during normal operation for fast reads and writes.
- Durable writes: Every create/update/delete inside a transaction is appended to on-disk transaction log files (*.trn). This is a write-ahead log approach.
- Startup recovery: On application startup, the library replays the transaction logs (and any snapshot, if present) to rebuild the in-memory model.
- Snapshots: You can create a compact on-disk snapshot (*.snp) of the current in-memory state. On the next startup, the snapshot is loaded first and only the newer transaction log files are replayed. This keeps startup time low without losing durability.
Tip: Call snapshot() periodically (or on controlled shutdown) and use removeOldFiles() to prune obsolete logs after a successful snapshot.
Advanced Features
Indexing
// Define complex indexes
val persistent = Persistent(
directory = File("data", "my-app"),
indexes = arrayOf(
index<Person>("ageOver30") { p -> ((p as? Person)?.age ?: 0) > 30 }
)
)
// Query using indexes
persistent.query {
findByIndex<Person>("ageOver30", true).forEach { person ->
println("Person over 30: ${person.name}")
}
}
Transactions
// Read-only query
persistent.query {
// Only read operations allowed
}
// Read-write transaction
persistent.transaction {
// Both read and write operations allowed
}
Snapshots and Maintenance
// Create a snapshot of the current state
persistent.snapshot()
// Remove old transaction log files
persistent.removeOldFiles()
License
This project is licensed under the MIT License - see the LICENSE file for details.
Languages
Kotlin
94.6%
Java
5.4%