2025-05-24 13:42:09 +02:00
2024-05-04 13:00:06 +02:00
2024-12-05 20:13:41 +01:00
2024-05-05 10:33:17 +02:00
2024-05-04 13:00:06 +02:00
2024-05-04 13:00:06 +02:00
2025-09-06 13:34:41 +02:00
2024-05-04 13:00:06 +02:00

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.4")
// Gradle Groovy DSL
implementation 'nl.astraeus:simple-persistence-kotlin:1.1.4'
<!-- Maven -->
<dependency>
    <groupId>nl.astraeus</groupId>
    <artifactId>simple-persistence-kotlin</artifactId>
    <version>1.1.4</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.

Description
No description provided
Readme MIT 221 KiB
Languages
Kotlin 94.6%
Java 5.4%