Fix currentTransaction in references while using query

This commit is contained in:
2024-05-06 20:50:29 +02:00
parent 68562160f1
commit 7eda90d30d
10 changed files with 136 additions and 133 deletions

View File

@@ -16,7 +16,19 @@ class Persistent(
val datastore: Datastore = Datastore(directory, indexes, enableOptimisticLocking) val datastore: Datastore = Datastore(directory, indexes, enableOptimisticLocking)
fun <T> query(block: Query.() -> T): T { fun <T> query(block: Query.() -> T): T {
return block(Query(this)) var cleanup = false
if (transactions.get() == null) {
transactions.set(Transaction(this))
cleanup = true
}
try {
return block(Query(this))
} finally {
if (cleanup) {
transactions.remove()
}
}
} }
fun transaction(block: Transaction.() -> Unit) { fun transaction(block: Transaction.() -> Unit) {

View File

@@ -10,7 +10,8 @@ inline fun <reified T : Persistable> reference(
) = Reference(T::class.java, initialValue) ) = Reference(T::class.java, initialValue)
inline fun <reified T : Persistable> nullableReference( inline fun <reified T : Persistable> nullableReference(
) = NullableReference(T::class.java) initialValue:T? = null
) = NullableReference(T::class.java, initialValue)
class Reference<S : Persistable>( class Reference<S : Persistable>(
val cls: Class<S>, val cls: Class<S>,
@@ -33,9 +34,10 @@ class Reference<S : Persistable>(
} }
class NullableReference<S : Persistable>( class NullableReference<S : Persistable>(
val cls: Class<S> val cls: Class<S>,
initialValue: S? = null
) : Serializable { ) : Serializable {
var id: Long? = null var id: Long? = initialValue?.id
operator fun getValue(thisRef: Persistable, property: KProperty<*>): S? { operator fun getValue(thisRef: Persistable, property: KProperty<*>): S? {
return currentTransaction()?.find(cls.kotlin, id ?: 0L) return currentTransaction()?.find(cls.kotlin, id ?: 0L)

View File

@@ -2,14 +2,13 @@ package nl.astraeus.persistence;
import nl.astraeus.nl.astraeus.persistence.AbstractPersistable; import nl.astraeus.nl.astraeus.persistence.AbstractPersistable;
import nl.astraeus.nl.astraeus.persistence.Index; import nl.astraeus.nl.astraeus.persistence.Index;
import nl.astraeus.nl.astraeus.persistence.Persistable;
import nl.astraeus.nl.astraeus.persistence.Persistent; import nl.astraeus.nl.astraeus.persistence.Persistent;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
public class TestPersistenceJava { public class TestPersistenceJava {
static class Person extends AbstractPersistable { static class Person extends AbstractPersistable {
@@ -100,7 +99,7 @@ public class TestPersistenceJava {
return null; return null;
}); });
persistent.transaction((t) -> { persistent.query((t) -> {
List<Person> persons = t.findByIndex( List<Person> persons = t.findByIndex(
Person.class, Person.class,
"name", "name",

View File

@@ -1,12 +1,12 @@
package nl.astraeus.persistence package nl.astraeus.persistence
import nl.astraeus.nl.astraeus.persistence.OptimisticLockingException import nl.astraeus.nl.astraeus.persistence.OptimisticLockingException
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent import nl.astraeus.nl.astraeus.persistence.Persistent
import nl.astraeus.nl.astraeus.persistence.TransactionLog import nl.astraeus.nl.astraeus.persistence.TransactionLog
import nl.astraeus.nl.astraeus.persistence.find import nl.astraeus.nl.astraeus.persistence.find
import nl.astraeus.nl.astraeus.persistence.findByIndex import nl.astraeus.nl.astraeus.persistence.findByIndex
import nl.astraeus.nl.astraeus.persistence.index import nl.astraeus.nl.astraeus.persistence.index
import nl.astraeus.persistence.domain.Person
import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import java.io.File import java.io.File
@@ -14,21 +14,6 @@ import kotlin.test.Test
class TestOptimisticLocking { class TestOptimisticLocking {
class Person(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val age: Int,
) : Persistable, Cloneable {
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String {
return "Person(id=$id, version=$version, name='$name', age=$age)"
}
}
@Test @Test
fun showTransactions() { fun showTransactions() {
val log = TransactionLog(File("data", "test-locking")) val log = TransactionLog(File("data", "test-locking"))

View File

@@ -1,13 +1,12 @@
package nl.astraeus.persistence package nl.astraeus.persistence
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent import nl.astraeus.nl.astraeus.persistence.Persistent
import nl.astraeus.nl.astraeus.persistence.TransactionLog import nl.astraeus.nl.astraeus.persistence.TransactionLog
import nl.astraeus.nl.astraeus.persistence.currentTransaction
import nl.astraeus.nl.astraeus.persistence.find import nl.astraeus.nl.astraeus.persistence.find
import nl.astraeus.nl.astraeus.persistence.findByIndex import nl.astraeus.nl.astraeus.persistence.findByIndex
import nl.astraeus.nl.astraeus.persistence.index import nl.astraeus.nl.astraeus.persistence.index
import nl.astraeus.nl.astraeus.persistence.reference.ReferenceCollection import nl.astraeus.persistence.domain.Company
import nl.astraeus.persistence.domain.Person
import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Assertions.assertNull
import java.io.File import java.io.File
@@ -15,51 +14,6 @@ import kotlin.test.Test
class TestPersistence { class TestPersistence {
class Company(
override var id: Long = 0,
override var version: Long = 0,
val name: String
) : Persistable, Cloneable {
val personIds: MutableList<Long> = ArrayList()
val persons: MutableCollection<Person>
get() {
return ReferenceCollection(Person::class.java, personIds)
}
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String {
return "Company(id=$id, version=$version, name='$name')"
}
}
class Person(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val age: Int,
private var companyId: Long? = null
) : Persistable, Cloneable {
var company: Company?
get() = currentTransaction()?.find(Company::class, companyId ?: 0L)
set(value) {
if (value != null) {
currentTransaction()?.store(value)
}
companyId = value?.id
}
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String {
return "Person(id=$id, version=$version, name='$name', age=$age, company=$companyId)"
}
}
@Test @Test
fun showTransactions() { fun showTransactions() {
val log = TransactionLog(File("data", "test-persistence")) val log = TransactionLog(File("data", "test-persistence"))

View File

@@ -0,0 +1,67 @@
package nl.astraeus.persistence
import nl.astraeus.nl.astraeus.persistence.Index
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent
import org.junit.jupiter.api.Test
import java.io.File
class TestPersistenceJavaInKotlin {
internal class Person(
var name: String,
var age: Int
) : Persistable {
override var id: Long = 0
override var version: Long = 0
companion object {
private const val serialVersionUID = 1L
}
}
@Test
fun testPersistence() {
println("TestPersistenceJavaInKotlin.testPersistence")
val persistent = Persistent(
File("data", "java-kotlin-test"),
arrayOf(
Index(
Person::class,
"name"
) { p -> (p as Person).name }
),
false
)
persistent.transaction {
val person = find(Person::class.java, 1L)
if (person != null) {
println("Person: ${person.name} is ${person.age} years old."
)
}
}
persistent.transaction {
val person = Person("John Doe", 42)
store(person)
}
persistent.query {
val persons = findByIndex(
Person::class.java,
"name",
"John Doe"
)
for (person in persons) {
println("Person: ${person.name} is ${person.age} years old.")
}
}
persistent.snapshot()
persistent.datastore.printStatus()
persistent.removeOldFiles()
}
}

View File

@@ -4,34 +4,17 @@ import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.Persistent import nl.astraeus.nl.astraeus.persistence.Persistent
import nl.astraeus.nl.astraeus.persistence.TransactionLog import nl.astraeus.nl.astraeus.persistence.TransactionLog
import nl.astraeus.nl.astraeus.persistence.reference.reference import nl.astraeus.nl.astraeus.persistence.reference.reference
import nl.astraeus.nl.astraeus.persistence.reference.referenceCollection import nl.astraeus.persistence.domain.Company
import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.assertThrows
import java.io.File import java.io.File
import kotlin.test.Test import kotlin.test.Test
class TestReferences { class TestReferences {
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
}
override fun toString(): String {
return "Company(id=$id, version=$version, name='$name', persons=${persons.size})"
}
}
class Person( class Person(
override var id: Long = 0, override var id: Long = 0,
override var version: Long = 0, override var version: Long = 0,
val name: String, val name: String,
val age: Int,
company: Company company: Company
) : Persistable, Cloneable { ) : Persistable, Cloneable {
var company: Company by reference(company) var company: Company by reference(company)
@@ -41,7 +24,7 @@ class TestReferences {
} }
override fun toString(): String { override fun toString(): String {
return "Person(id=$id, version=$version, name='$name', age=$age)" return "Person(id=$id, version=$version, name='$name')"
} }
} }
@@ -67,13 +50,10 @@ class TestReferences {
val person = Person( val person = Person(
id = 0L, id = 0L,
name = "John Doe", name = "John Doe",
age = 25,
company = company company = company
) )
store(person) store(person)
company.persons.add(person)
store(company) store(company)
for (p in company.persons) { for (p in company.persons) {

View File

@@ -7,52 +7,14 @@ import nl.astraeus.nl.astraeus.persistence.TransactionLog
import nl.astraeus.nl.astraeus.persistence.count import nl.astraeus.nl.astraeus.persistence.count
import nl.astraeus.nl.astraeus.persistence.index import nl.astraeus.nl.astraeus.persistence.index
import nl.astraeus.nl.astraeus.persistence.searchIndex import nl.astraeus.nl.astraeus.persistence.searchIndex
import nl.astraeus.persistence.domain.Company
import nl.astraeus.persistence.domain.Person
import java.io.File import java.io.File
import kotlin.random.Random import kotlin.random.Random
import kotlin.test.Test import kotlin.test.Test
class TestThreaded { class TestThreaded {
class Company(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val adres: String = "Blaat"
) : Persistable, Cloneable {
//var persons: MutableList<Person> by ListReference<Person, Company>(Person::class.java)
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String {
return "Company(id=$id, version=$version, name='$name', adres='$adres')"
}
}
class Person(
override var id: Long = 0,
override var version: Long = 0,
val name: String,
val age: Int,
var companyId: Long? = null
) : Persistable, Cloneable {
/* var company: Company? by Reference(
Company::class.java,
{ id -> companyId = id },
{ companyId }
)*/
companion object {
private const val serialVersionUID: Long = 1L
}
override fun toString(): String {
return "Person(id=$id, version=$version, name='$name', age=$age)"
}
}
@Test @Test
fun showTransactions() { fun showTransactions() {
val log = TransactionLog(File("data", "test-threaded")) val log = TransactionLog(File("data", "test-threaded"))

View File

@@ -0,0 +1,20 @@
package nl.astraeus.persistence.domain
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.reference.referenceCollection
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
}
override fun toString(): String {
return "Company(id=$id, version=$version, name='$name', persons=${persons.size})"
}
}

View File

@@ -0,0 +1,22 @@
package nl.astraeus.persistence.domain
import nl.astraeus.nl.astraeus.persistence.Persistable
import nl.astraeus.nl.astraeus.persistence.reference.nullableReference
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
}
override fun toString(): String {
return "Person(id=$id, version=$version, name='$name', age=$age)"
}
}