From 8c47f88dad0d454cd5f8cae007c72c1ed206ed5d Mon Sep 17 00:00:00 2001 From: Andreas Ernst Date: Mon, 23 Sep 2024 11:49:55 +0200 Subject: [PATCH] multi valued relations starting to work --- .../kotlin/org/sirius/common/tracer/Tracer.kt | 2 +- .../kotlin/org/sirius/dorm/ObjectManager.kt | 22 +-- .../org/sirius/dorm/model/ObjectDescriptor.kt | 6 +- .../sirius/dorm/model/PropertyDescriptor.kt | 13 +- .../org/sirius/dorm/object/DataObject.kt | 22 ++- .../sirius/dorm/object/MultiValuedRelation.kt | 140 +++++++++++++++++- .../kotlin/org/sirius/dorm/object/Property.kt | 8 + .../kotlin/org/sirius/dorm/object/Relation.kt | 5 + .../dorm/object/SingleValuedRelation.kt | 14 +- .../dorm/persistence/DataObjectMapper.kt | 20 +-- .../org/sirius/dorm/query/QueryManager.kt | 14 +- .../dorm/transaction/TransactionState.kt | 16 ++ .../kotlin/org/sirius/dorm/AbstractTest.kt | 6 +- .../kotlin/org/sirius/dorm/RelationTests.kt | 54 ++++++- src/test/kotlin/org/sirius/dorm/TracerTest.kt | 17 ++- src/test/resources/application.yml | 2 +- 16 files changed, 297 insertions(+), 64 deletions(-) diff --git a/src/main/kotlin/org/sirius/common/tracer/Tracer.kt b/src/main/kotlin/org/sirius/common/tracer/Tracer.kt index 1762c34..baf7f0f 100644 --- a/src/main/kotlin/org/sirius/common/tracer/Tracer.kt +++ b/src/main/kotlin/org/sirius/common/tracer/Tracer.kt @@ -31,7 +31,7 @@ class Tracer(private val trace: org.sirius.common.tracer.Trace, layout : String fun trace(path: String, level: TraceLevel, message: String, vararg args: Any) { if (this.isTraced(path, level)) - this.trace.trace(org.sirius.common.tracer.TraceEntry(path, level, message.format(*args), Date()), formatter) + this.trace.trace(TraceEntry(path, level, message.format(*args), Date()), formatter) } // private diff --git a/src/main/kotlin/org/sirius/dorm/ObjectManager.kt b/src/main/kotlin/org/sirius/dorm/ObjectManager.kt index 0f382e2..f7c95ab 100644 --- a/src/main/kotlin/org/sirius/dorm/ObjectManager.kt +++ b/src/main/kotlin/org/sirius/dorm/ObjectManager.kt @@ -9,8 +9,6 @@ import org.sirius.dorm.`object`.DataObject import org.sirius.dorm.persistence.DataObjectMapper import org.sirius.dorm.persistence.entity.EntityEntity import org.sirius.dorm.query.* -import org.sirius.dorm.query.parser.OQLLexer -import org.sirius.dorm.query.parser.OQLParser import org.sirius.dorm.transaction.Status import org.sirius.dorm.transaction.TransactionState import org.sirius.common.type.Type @@ -126,7 +124,7 @@ class ObjectManager() { fun create(objectDescriptor: ObjectDescriptor) : DataObject { val obj = objectDescriptor.create() - transactionState().create(obj) + TransactionState.current().create(obj) return obj } @@ -139,33 +137,29 @@ class ObjectManager() { // tx fun begin() { - transactionState.set(TransactionState(this, transactionManager)) + TransactionState.set(this, transactionManager) } fun commit() { try { - transactionState().commit(mapper) + TransactionState.current().commit(mapper) } finally { mapper.clear() - transactionState.remove() + TransactionState.remove() } } fun rollback() { try { - transactionState().rollback(mapper) + TransactionState.current().rollback(mapper) } finally { mapper.clear() - transactionState.remove() + TransactionState.remove() } } - fun transactionState() : TransactionState { - return transactionState.get() - } - fun queryManager() : QueryManager { return QueryManager(this, entityManager, mapper) } @@ -190,7 +184,7 @@ class ObjectManager() { val entity = entityManager.find(EntityEntity::class.java, id) return if ( entity !== null) - mapper.read(transactionState(), descriptor, entity) + mapper.read(TransactionState.current(), descriptor, entity) else null } @@ -198,8 +192,6 @@ class ObjectManager() { // companion companion object { - val transactionState = ThreadLocal() - lateinit var instance : ObjectManager } } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptor.kt b/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptor.kt index a3db8be..9b7219a 100644 --- a/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptor.kt +++ b/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptor.kt @@ -20,8 +20,8 @@ class ObjectDescriptor(val name: String, val properties: Array { - return properties.map { property -> property.createProperty(null) }.toTypedArray() + fun createValues(obj: DataObject): Array { + return properties.map { property -> property.createProperty(obj, null) }.toTypedArray() } fun resolve(objectManager: ObjectManager) { @@ -31,7 +31,7 @@ class ObjectDescriptor(val name: String, val properties: Array { diff --git a/src/main/kotlin/org/sirius/dorm/model/PropertyDescriptor.kt b/src/main/kotlin/org/sirius/dorm/model/PropertyDescriptor.kt index ea6fb79..7f9fcd0 100644 --- a/src/main/kotlin/org/sirius/dorm/model/PropertyDescriptor.kt +++ b/src/main/kotlin/org/sirius/dorm/model/PropertyDescriptor.kt @@ -6,17 +6,14 @@ package org.sirius.dorm.model */ import org.sirius.dorm.* -import org.sirius.dorm.`object`.Attribute -import org.sirius.dorm.`object`.MultiValuedRelation -import org.sirius.dorm.`object`.Property -import org.sirius.dorm.`object`.SingleValuedRelation import org.sirius.dorm.persistence.entity.AttributeEntity import org.sirius.common.type.Type +import org.sirius.dorm.`object`.* abstract class PropertyDescriptor(val name: String) { var index = 0 - abstract fun createProperty(entity: AttributeEntity?) : Property + abstract fun createProperty(obj: DataObject, entity: AttributeEntity?) : Property abstract fun defaultValue() : Any? @@ -47,7 +44,7 @@ class AttributeDescriptor(name: String, val type: Type, val isPrimaryK // override - override fun createProperty(entity: AttributeEntity?) : Property { + override fun createProperty(obj: DataObject, entity: AttributeEntity?) : Property { return Attribute(entity, defaultValue()!!) } @@ -82,8 +79,8 @@ open class RelationDescriptor(name: String, val target: String, val multi // override - override fun createProperty(entity: AttributeEntity?) : Property { - return if ( multiplicity === Multiplicity.ONE ) SingleValuedRelation(entity, targetDescriptor!!) else MultiValuedRelation(entity, targetDescriptor!!) + override fun createProperty(obj: DataObject, entity: AttributeEntity?) : Property { + return if ( multiplicity === Multiplicity.ONE ) SingleValuedRelation(obj, entity, targetDescriptor!!) else MultiValuedRelation(obj, entity, targetDescriptor!!) } override fun resolve(objectManager: ObjectManager, descriptor: ObjectDescriptor) { diff --git a/src/main/kotlin/org/sirius/dorm/object/DataObject.kt b/src/main/kotlin/org/sirius/dorm/object/DataObject.kt index 09a7e5b..a6f3470 100644 --- a/src/main/kotlin/org/sirius/dorm/object/DataObject.kt +++ b/src/main/kotlin/org/sirius/dorm/object/DataObject.kt @@ -11,10 +11,11 @@ import org.sirius.dorm.persistence.entity.EntityEntity import org.sirius.dorm.transaction.ObjectState -class DataObject(val type: ObjectDescriptor, var state : ObjectState?, val values: Array) { +class DataObject(val type: ObjectDescriptor, var state : ObjectState?) { // instance data var entity: EntityEntity? = null + val values = type.createValues(this) // public @@ -37,11 +38,11 @@ class DataObject(val type: ObjectDescriptor, var state : ObjectState?, val value // public operators - fun value(index: Int) : T { + fun value(index: Int) : T { // TODO??? return values[index].get(objectManager) as T } - /*fun reference(index: Int) : SingleValuedRelation { + /*fun reference(index: Int) : SingleValuedRelation { TODO return values[index] as SingleValuedRelation } @@ -66,7 +67,20 @@ class DataObject(val type: ObjectDescriptor, var state : ObjectState?, val value values[property.index].set(property, value) } + // override Object + + override fun equals(other: Any?): Boolean { + if ( other is DataObject) + return id == other.id && this.type === other.type + else + return false + } + + override fun hashCode(): Int { + return type.hashCode() + id.hashCode() + } + companion object { - val NONE = DataObject(ObjectDescriptor("none", arrayOf()), null, arrayOf()) + val NONE = DataObject(ObjectDescriptor("none", arrayOf()), null) } } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt b/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt index 00a84e1..26c25f3 100644 --- a/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt @@ -1,23 +1,153 @@ package org.sirius.dorm.`object` +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ import org.sirius.dorm.ObjectManager import org.sirius.dorm.model.ObjectDescriptor import org.sirius.dorm.model.PropertyDescriptor import org.sirius.dorm.persistence.entity.AttributeEntity +import org.sirius.dorm.persistence.entity.EntityEntity +import org.sirius.dorm.transaction.TransactionState +import java.util.HashMap + +class MultiValuedRelation(val obj: DataObject, property: AttributeEntity?, val targetDescriptor: ObjectDescriptor) : Relation(property), MutableSet { + // instance data + + private var objects : HashSet? = null + + // private + + private fun isLoaded() : Boolean { + return objects !== null + } + + private fun load(objectManager: ObjectManager) { + objects = HashSet() + for ( target in property!!.relations ) { + objects!!.add(objectManager.mapper.read(TransactionState.current(), targetDescriptor, target)) + } + } + + private fun markDirty() { + if ( obj.state!!.snapshot == null) + obj.state!!.takeSnapshot(obj) + } + + // implement Property -class MultiValuedRelation(property: AttributeEntity?, targetDescriptor: ObjectDescriptor) : Relation(property) { override fun get(objectManager: ObjectManager) : Any? { - return null // TODO RELATION + if ( !isLoaded()) + load(objectManager) + + return this } override fun set(propertyDescriptor: PropertyDescriptor, value: Any?) : Boolean { - // TODO RELATIONthis.value = value!! - return true + throw Error("relations don't allow to be set") } override fun save(): Any { return this } - override fun restore(state: Any) {} + override fun restore(state: Any) { + } + + override fun isDirty(snapshot: Any) : Boolean { + return isLoaded() + } + + override fun flush() { + if (isLoaded()) { + // synchronize the objects set with the property.relations + + val targetMap = HashMap() + val relations = property!!.relations + + // collect all targets in a map + + for (previousTarget in relations) + targetMap[previousTarget.id] = previousTarget + + // iterate over source objects + + for (target in objects!!) { + val key = target.id + + if (!targetMap.containsKey(key)) + relations.add(target.entity!!) + else + targetMap.remove(key) + } // for + + // deleted + + for (deleted in targetMap.values) { + relations.remove(deleted) + } // if + } + } + + // implement MutableSet + + override fun add(element: DataObject): Boolean { + markDirty() + + return objects!!.add(element) + } + + override fun addAll(elements: Collection): Boolean { + var result = false + for (element in elements) + if (add(element)) + result = true + + return result + } + + override fun remove(element: DataObject): Boolean { + markDirty() + + return objects!!.remove(element) + } + + override val size: Int + get() = objects!!.size + + override fun clear() { + markDirty() + + return objects!!.clear() + } + + override fun isEmpty(): Boolean { + return size == 0 + } + + override fun containsAll(elements: Collection): Boolean { + return objects!!.containsAll(elements) + } + + override fun contains(element: DataObject): Boolean { + return objects!!.contains(element) + } + + override fun iterator(): MutableIterator { + return objects!!.iterator() + } + + override fun retainAll(elements: Collection): Boolean { + markDirty() + + return objects!!.retainAll(elements) + } + + override fun removeAll(elements: Collection): Boolean { + markDirty() + + return objects!!.removeAll(elements) + } } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/object/Property.kt b/src/main/kotlin/org/sirius/dorm/object/Property.kt index fc2dda4..a101ad3 100644 --- a/src/main/kotlin/org/sirius/dorm/object/Property.kt +++ b/src/main/kotlin/org/sirius/dorm/object/Property.kt @@ -2,15 +2,23 @@ package org.sirius.dorm.`object` import org.sirius.dorm.ObjectManager import org.sirius.dorm.model.PropertyDescriptor +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ abstract class Property() { abstract fun get(objectManager: ObjectManager) : Any? + abstract fun set(propertyDescriptor: PropertyDescriptor, value: Any?) : Boolean + open fun init(propertyDescriptor: PropertyDescriptor, value: Any?) { this.set(propertyDescriptor, value) } // snapshot stuff + abstract fun save(): Any; abstract fun restore(state: Any); diff --git a/src/main/kotlin/org/sirius/dorm/object/Relation.kt b/src/main/kotlin/org/sirius/dorm/object/Relation.kt index e597037..265d7e8 100644 --- a/src/main/kotlin/org/sirius/dorm/object/Relation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/Relation.kt @@ -1,4 +1,9 @@ package org.sirius.dorm.`object` +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ import org.sirius.dorm.persistence.entity.AttributeEntity diff --git a/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt b/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt index 0e1cae5..55bbc58 100644 --- a/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt @@ -1,11 +1,17 @@ package org.sirius.dorm.`object` +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ import org.sirius.dorm.ObjectManager import org.sirius.dorm.model.ObjectDescriptor import org.sirius.dorm.model.PropertyDescriptor import org.sirius.dorm.persistence.entity.AttributeEntity +import org.sirius.dorm.transaction.TransactionState -class SingleValuedRelation(property: AttributeEntity?, val targetDescriptor: ObjectDescriptor) : Relation(property) { +class SingleValuedRelation(val obj: DataObject, property: AttributeEntity?, val targetDescriptor: ObjectDescriptor) : Relation(property) { // instance data var target: DataObject? = DataObject.NONE @@ -18,6 +24,10 @@ class SingleValuedRelation(property: AttributeEntity?, val targetDescriptor: Obj // override + override fun isDirty(snapshot: Any) : Boolean { + return isLoaded() + } + override fun flush() { if ( isLoaded()) { property!!.relations.clear() @@ -30,7 +40,7 @@ class SingleValuedRelation(property: AttributeEntity?, val targetDescriptor: Obj if ( !isLoaded() && property !== null) { if ( property!!.relations.size == 1) { val targetEntity = property!!.relations.first() - target = objectManager.mapper.read(objectManager.transactionState(), targetDescriptor, targetEntity) + target = objectManager.mapper.read(TransactionState.current(), targetDescriptor, targetEntity) } else target = null diff --git a/src/main/kotlin/org/sirius/dorm/persistence/DataObjectMapper.kt b/src/main/kotlin/org/sirius/dorm/persistence/DataObjectMapper.kt index 700890d..079628a 100644 --- a/src/main/kotlin/org/sirius/dorm/persistence/DataObjectMapper.kt +++ b/src/main/kotlin/org/sirius/dorm/persistence/DataObjectMapper.kt @@ -40,17 +40,18 @@ class DataObjectMapper() { fun update(state: TransactionState, obj: DataObject) { if ( Tracer.ENABLED) - Tracer.trace("com.quasar.dorm", TraceLevel.HIGH, "update %s", obj.type.name) + Tracer.trace("sirius.sirius.dorm", TraceLevel.HIGH, "update %s[%d]", obj.type.name, obj.id) val builder = entityManager.criteriaBuilder val objectManager = state.objectManager + val snapshot = obj.state!!.snapshot!! // update attributes val properties = obj.type.properties for ( index in 1..("id"), obj.id)) @@ -91,22 +92,23 @@ class DataObjectMapper() { fun delete(state: TransactionState, obj: DataObject) { if ( Tracer.ENABLED) - Tracer.trace("com.quasar.dorm", TraceLevel.HIGH, "read %s", obj.type.name) + Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "delete %s[%d]", obj.type.name, obj.id) entityManager.remove(obj.entity!!) } fun create(state: TransactionState, obj: DataObject) { - if ( Tracer.ENABLED) - Tracer.trace("com.quasar.dorm", TraceLevel.HIGH, "create %s", obj.type.name) - val descriptor = obj.type obj.entity = EntityEntity(0, descriptor.name, mapper.writeValueAsString(obj)) entityManager.persist(obj.entity) // we need the id...is that required, think of a lifecycle hook? + if ( Tracer.ENABLED) + Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "create %s[%d]", obj.type.name, obj.entity!!.id) + + writer4(descriptor).write(state, obj, entityManager) // will create the attribute entities // set as value as well @@ -134,7 +136,7 @@ class DataObjectMapper() { fun read(state: TransactionState, objectDescriptor: ObjectDescriptor, entity: EntityEntity): DataObject { return state.retrieve(entity.id) { if ( Tracer.ENABLED) - Tracer.trace("com.quasar.dorm", TraceLevel.HIGH, "read %s", objectDescriptor.name) + Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "read %s", objectDescriptor.name) val obj = objectDescriptor.create() @@ -156,7 +158,7 @@ class DataObjectMapper() { fun read(state: TransactionState, objectDescriptor: ObjectDescriptor, attributes: List, start: Int, end: Int) : DataObject { return state.retrieve(attributes[start].entity.id) { if ( Tracer.ENABLED) - Tracer.trace("com.quasar.dorm", TraceLevel.HIGH, "read %s", objectDescriptor.name) + Tracer.trace("com.sirius.dorm", TraceLevel.HIGH, "read %s[%d]", objectDescriptor.name, attributes[start].entity.id) val obj = objectDescriptor.create() diff --git a/src/main/kotlin/org/sirius/dorm/query/QueryManager.kt b/src/main/kotlin/org/sirius/dorm/query/QueryManager.kt index 8c15b6b..1a25761 100644 --- a/src/main/kotlin/org/sirius/dorm/query/QueryManager.kt +++ b/src/main/kotlin/org/sirius/dorm/query/QueryManager.kt @@ -15,6 +15,7 @@ import org.sirius.dorm.transaction.TransactionState import jakarta.persistence.EntityManager import jakarta.persistence.criteria.CriteriaQuery import jakarta.persistence.criteria.Root +import org.sirius.dorm.persistence.entity.EntityEntity class QueryManager(val objectManager: ObjectManager, private val entityManager: EntityManager, private val mapper: DataObjectMapper) { // instance data @@ -47,9 +48,9 @@ class QueryManager(val objectManager: ObjectManager, private val entityManager: private fun computeQueryResult(objectQuery: Query, executor: QueryExecutor) : List { // flush managed objects that could influence query results - // currently this is onle the roor, since we don't support joins yet + // currently this is only the root, since we don't support joins yet - executor.queryManager.objectManager.transactionState().flush(objectQuery.root!!.objectDescriptor) + TransactionState.current().flush(objectQuery.root!!.objectDescriptor) // create main query @@ -59,6 +60,7 @@ class QueryManager(val objectManager: ObjectManager, private val entityManager: criteriaQuery.select(attributeEntity) + //TODO builder.equal(attributeEntity.get("type"), objectQuery.root!!.objectDescriptor.name), if ( objectQuery.where != null) criteriaQuery.where( objectQuery.where!!.createWhere(executor as QueryExecutor, builder, criteriaQuery as CriteriaQuery, attributeEntity as Root), @@ -82,8 +84,12 @@ class QueryManager(val objectManager: ObjectManager, private val entityManager: if ( objectQuery.where !== null) criteriaQuery.where( + builder.equal(attributeEntity.get("type"), objectQuery.root!!.objectDescriptor.name), objectQuery.where!!.createWhere(executor as QueryExecutor, builder, criteriaQuery as CriteriaQuery, attributeEntity as Root), ) + else criteriaQuery.where( + builder.equal(attributeEntity.get("type"), objectQuery.root!!.objectDescriptor.name), + ) criteriaQuery.orderBy(builder.asc(attributeEntity.get("entity"))) @@ -92,13 +98,13 @@ class QueryManager(val objectManager: ObjectManager, private val entityManager: // compute result - val state = objectManager.transactionState() + val state = TransactionState.transactionState() val objectDescriptor = objectQuery.root!!.objectDescriptor return entities.map { entity -> mapper.readFromEntity(state, objectDescriptor, entity) } as List */ - return computeObjectResultFromAttributes(objectQuery.root!!.objectDescriptor, objectManager.transactionState(), entityManager.createQuery(criteriaQuery).resultList as List) as List + return computeObjectResultFromAttributes(objectQuery.root!!.objectDescriptor, TransactionState.current(), entityManager.createQuery(criteriaQuery).resultList as List) as List } } diff --git a/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt b/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt index c89b430..d7c04c9 100644 --- a/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt +++ b/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt @@ -119,4 +119,20 @@ class TransactionState(val objectManager: ObjectManager, val transactionManager: executeOperations() } + + companion object { + private val current = ThreadLocal() + + fun current() : TransactionState { + return current.get() + } + + fun set(objectManager: ObjectManager, transactionManager: PlatformTransactionManager) { + current.set(TransactionState(objectManager, transactionManager)) + } + + fun remove() { + current.remove() + } + } } \ No newline at end of file diff --git a/src/test/kotlin/org/sirius/dorm/AbstractTest.kt b/src/test/kotlin/org/sirius/dorm/AbstractTest.kt index 114f5e8..d67293a 100644 --- a/src/test/kotlin/org/sirius/dorm/AbstractTest.kt +++ b/src/test/kotlin/org/sirius/dorm/AbstractTest.kt @@ -42,19 +42,19 @@ class AbstractTest { Tracer(ConsoleTrace(), "%t{yyyy-MM-dd HH:mm:ss,SSS} %l{-10s} [%p] %m") .setTraceLevel("", TraceLevel.OFF) .setTraceLevel("com", TraceLevel.LOW) - .setTraceLevel("com.quasar.dorm", TraceLevel.HIGH) + .setTraceLevel("com.sirius.dorm", TraceLevel.HIGH) } lateinit var statistics : Statistics; - @BeforeEach + //@BeforeEach fun clearStats() { val session = entityManager.unwrap(Session::class.java) statistics = session.getSessionFactory().getStatistics() } - @AfterEach + //@AfterEach fun printStats() { for ( query in statistics.queries) println(query) diff --git a/src/test/kotlin/org/sirius/dorm/RelationTests.kt b/src/test/kotlin/org/sirius/dorm/RelationTests.kt index 4ccccc0..1400c2d 100644 --- a/src/test/kotlin/org/sirius/dorm/RelationTests.kt +++ b/src/test/kotlin/org/sirius/dorm/RelationTests.kt @@ -7,6 +7,10 @@ package org.sirius.dorm import org.sirius.dorm.`object`.DataObject import org.junit.jupiter.api.Test +import org.sirius.common.type.base.* +import org.sirius.dorm.model.Multiplicity +import org.sirius.dorm.model.ObjectDescriptor +import org.sirius.dorm.`object`.MultiValuedRelation import kotlin.test.assertEquals @@ -42,7 +46,55 @@ class RelationTests: AbstractTest() { assert(father !== null) - assertEquals("helmut", father!!["name"]) + assertEquals("Helmut", father!!["name"]) + } + } + + @Test + fun testOneToMany() { + // create schema + + var descriptor : ObjectDescriptor?= null + withTransaction { + descriptor = objectManager.type("p") + .attribute("name", string()) + .relation("children", "p", Multiplicity.ZERO_OR_MANY) + .register() + } + + // test + + var id = 0 + + withTransaction { + val person = objectManager.create(descriptor!!) + + person["name"] = "Andi" + + id = person.id + + val child = objectManager.create(descriptor!!) + + child["name"] = "Nika" + + // add as child + + (person["children"] as MultiValuedRelation).add(child) + } + + // reread + + withTransaction { + val person = objectManager.findById(descriptor!!, id) + + assert(person !== null) + + assert(person!!["children"] !== null) + + val children : MultiValuedRelation = person!!["children"] as MultiValuedRelation + + assert(children.size == 1) + //assertEquals("Nika", children[0]["name"]) } } } \ No newline at end of file diff --git a/src/test/kotlin/org/sirius/dorm/TracerTest.kt b/src/test/kotlin/org/sirius/dorm/TracerTest.kt index 0e7ef29..4653f7e 100644 --- a/src/test/kotlin/org/sirius/dorm/TracerTest.kt +++ b/src/test/kotlin/org/sirius/dorm/TracerTest.kt @@ -1,15 +1,16 @@ package org.sirius.dorm +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ import org.sirius.common.tracer.TraceLevel import org.sirius.common.tracer.Tracer import org.sirius.common.tracer.trace.ConsoleTrace import org.junit.jupiter.api.Test -/* - * @COPYRIGHT (C) 2023 Andreas Ernst - * - * All rights reserved - */ + class TracerTest { @Test fun testTracer() { @@ -18,14 +19,14 @@ class TracerTest { tracer .setTraceLevel("", TraceLevel.OFF) .setTraceLevel("com", TraceLevel.LOW) - .setTraceLevel("com.quasar", TraceLevel.MEDIUM) + .setTraceLevel("com.sirius", TraceLevel.MEDIUM) assert(!tracer.isTraced("", TraceLevel.FULL)) assert(tracer.isTraced("com", TraceLevel.LOW)) assert(tracer.isTraced("com.foo.bar", TraceLevel.LOW)) - Tracer.trace("com.quasar", TraceLevel.LOW, "hello world") - Tracer.trace("com.quasar", TraceLevel.MEDIUM, "hello world") + Tracer.trace("com.sirius", TraceLevel.LOW, "hello world") + Tracer.trace("com.sirius", TraceLevel.MEDIUM, "hello world") } } \ No newline at end of file diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index dac6b03..0ed287d 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -12,7 +12,7 @@ spring: hibernate: format_sql: false generate_statistics: true - show-sql: false + show-sql: true defer-datasource-initialization: true hibernate: ddl-auto: update