From a0b3564b9d19c0551e13e1bdd6507847111fd6c4 Mon Sep 17 00:00:00 2001 From: Andreas Ernst Date: Thu, 26 Sep 2024 11:57:47 +0200 Subject: [PATCH] refactored builder and introduced owner property --- .../kotlin/org/sirius/dorm/ObjectManager.kt | 40 ----- .../sirius/dorm/model/AttributeDescriptor.kt | 2 +- .../dorm/model/ObjectDescriptorBuilder.kt | 145 ++++++++++++++++++ .../sirius/dorm/model/RelationDescriptor.kt | 4 +- .../json/ObjectDescriptorDeserializer.kt | 3 +- .../model/json/ObjectDescriptorSerializer.kt | 1 + .../sirius/dorm/object/MultiValuedRelation.kt | 8 +- .../kotlin/org/sirius/dorm/object/Relation.kt | 4 +- .../dorm/object/SingleValuedRelation.kt | 8 +- .../sirius/dorm/persistence/ObjectReader.kt | 2 +- .../sirius/dorm/persistence/ObjectWriter.kt | 10 +- .../org/sirius/dorm/query/ObjectPath.kt | 2 +- .../org/sirius/dorm/query/PropertyPath.kt | 2 +- .../dorm/transaction/TransactionState.kt | 4 +- .../kotlin/org/sirius/dorm/AbstractTest.kt | 24 +-- .../kotlin/org/sirius/dorm/DORMBenchmark.kt | 4 +- .../kotlin/org/sirius/dorm/RelationTests.kt | 41 ++--- 17 files changed, 207 insertions(+), 97 deletions(-) create mode 100644 src/main/kotlin/org/sirius/dorm/model/ObjectDescriptorBuilder.kt diff --git a/src/main/kotlin/org/sirius/dorm/ObjectManager.kt b/src/main/kotlin/org/sirius/dorm/ObjectManager.kt index efa4484..c752193 100644 --- a/src/main/kotlin/org/sirius/dorm/ObjectManager.kt +++ b/src/main/kotlin/org/sirius/dorm/ObjectManager.kt @@ -11,14 +11,11 @@ import org.sirius.dorm.persistence.entity.EntityEntity import org.sirius.dorm.query.* import org.sirius.dorm.transaction.Status import org.sirius.dorm.transaction.TransactionState -import org.sirius.common.type.Type -import org.sirius.common.type.base.int import jakarta.persistence.EntityManager import jakarta.persistence.PersistenceContext import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.RecognitionException -import org.sirius.common.type.base.long import org.sirius.dorm.query.parser.OQLParser import org.springframework.beans.factory.annotation.Autowired import org.springframework.jdbc.core.JdbcTemplate @@ -26,43 +23,6 @@ import org.springframework.stereotype.Component import org.springframework.transaction.PlatformTransactionManager import java.util.concurrent.ConcurrentHashMap - -class ObjectDescriptorBuilder(val manager: ObjectManager, val name: String) { - // instance data - - private val properties = ArrayList>() - - init { - attribute("id", long(), true) - } - - // fluent - - fun attribute(name: String, type: Type, isPrimaryKey: Boolean = false) : ObjectDescriptorBuilder { - properties.add(AttributeDescriptor(name, type as Type, isPrimaryKey)) - - return this - } - - fun relation(name: String, target: String, multiplicity: Multiplicity, cascade: Cascade? = null) : ObjectDescriptorBuilder { - properties.add(RelationDescriptor(name, target, multiplicity, cascade, null)) - - return this - } - - fun relation(name: String, target: String, multiplicity: Multiplicity, inverse: String, cascade: Cascade? = null) : ObjectDescriptorBuilder { - properties.add(RelationDescriptor(name, target, multiplicity, cascade, inverse)) - - return this - } - - // public - - fun register() { - manager.register( ObjectDescriptor(name, properties.toTypedArray())) - } -} - @Component class ObjectManager() { // instance data diff --git a/src/main/kotlin/org/sirius/dorm/model/AttributeDescriptor.kt b/src/main/kotlin/org/sirius/dorm/model/AttributeDescriptor.kt index 9e7b15e..7048ff2 100644 --- a/src/main/kotlin/org/sirius/dorm/model/AttributeDescriptor.kt +++ b/src/main/kotlin/org/sirius/dorm/model/AttributeDescriptor.kt @@ -12,7 +12,7 @@ import org.sirius.dorm.`object`.Property import org.sirius.dorm.persistence.entity.PropertyEntity import org.sirius.dorm.transaction.Status -class AttributeDescriptor(name: String, val type: Type, val isPrimaryKey : Boolean = false) : PropertyDescriptor(name) { +class AttributeDescriptor(name: String, val type: Type<*>, val isPrimaryKey : Boolean = false) : PropertyDescriptor(name) { // public fun baseType() : Class<*> { diff --git a/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptorBuilder.kt b/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptorBuilder.kt new file mode 100644 index 0000000..15091fb --- /dev/null +++ b/src/main/kotlin/org/sirius/dorm/model/ObjectDescriptorBuilder.kt @@ -0,0 +1,145 @@ +package org.sirius.dorm.model +/* + * @COPYRIGHT (C) 2023 Andreas Ernst + * + * All rights reserved + */ + +import org.sirius.common.type.Type +import org.sirius.common.type.base.long +import org.sirius.dorm.ObjectManager + + +abstract class PropertyBuilder() { + // instance data + + protected var name = "" + + // protected + + abstract fun build() : PropertyDescriptor +} +class AttributeBuilder() : PropertyBuilder() { + // instance data + + private var primaryKey = false + private var type: Type<*>? = null + + // fluent + + fun name(name: String) : AttributeBuilder { + this.name = name + + return this + } + + fun type(type: Type<*>) : AttributeBuilder { + this.type = type + + return this + } + + fun primaryKey() : AttributeBuilder { + this.primaryKey = true + + return this + } + + // public + + override fun build() : AttributeDescriptor { + // done + + return AttributeDescriptor(name, type!!, primaryKey) + } +} + +fun attribute(name: String) : AttributeBuilder { + return AttributeBuilder().name(name) +} + +class RelationBuilder() : PropertyBuilder() { + // instance data + + private var target = "" + private var multiplicity : Multiplicity? = null + private var cascade : Cascade? = null + private var inverse : String? = null + private var owner = false + + // fluent + + fun name(name: String) : RelationBuilder { + this.name = name + + return this + } + + fun target(target: String) : RelationBuilder { + this.target = target + + return this + } + + fun inverse(inverse: String) : RelationBuilder { + this.inverse = inverse + + return this + } + + fun multiplicity(multiplicity: Multiplicity) : RelationBuilder { + this.multiplicity = multiplicity + + return this + } + + fun cascade(cascade: Cascade) : RelationBuilder { + this.cascade = cascade + + return this + } + + fun owner() : RelationBuilder { + this.owner = true + + return this + } + + // build + + override fun build() : RelationDescriptor { + return RelationDescriptor(name, target, multiplicity!!, cascade, inverse, owner) + } +} + +fun relation(name: String) : RelationBuilder { + return RelationBuilder().name(name) +} + +class ObjectDescriptorBuilder(val manager: ObjectManager, val name: String) { + // instance data + + private val properties = ArrayList>() + + init { + property(id) + } + + // fluent + + fun property(propertyBuilder: PropertyBuilder) : ObjectDescriptorBuilder { + properties.add(propertyBuilder.build()) + + return this + } + + // public + + fun register() { + manager.register(ObjectDescriptor(name, properties.toTypedArray())) + } + + companion object { + val id = attribute("id").type(long()).primaryKey() + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/model/RelationDescriptor.kt b/src/main/kotlin/org/sirius/dorm/model/RelationDescriptor.kt index 16a26d5..21bbf73 100644 --- a/src/main/kotlin/org/sirius/dorm/model/RelationDescriptor.kt +++ b/src/main/kotlin/org/sirius/dorm/model/RelationDescriptor.kt @@ -13,7 +13,7 @@ import org.sirius.dorm.`object`.SingleValuedRelation import org.sirius.dorm.persistence.entity.PropertyEntity import org.sirius.dorm.transaction.Status -open class RelationDescriptor(name: String, val target: String, val multiplicity: Multiplicity, val cascade: Cascade?, val inverse: String?) : PropertyDescriptor(name) { +open class RelationDescriptor(name: String, val target: String, val multiplicity: Multiplicity, val cascade: Cascade?, val inverse: String?, val owner: Boolean) : PropertyDescriptor(name) { // instance data var targetDescriptor: ObjectDescriptor? = null @@ -55,6 +55,6 @@ open class RelationDescriptor(name: String, val target: String, val multi } fun isOwner() : Boolean { - return inverse !== null + return owner } } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorDeserializer.kt b/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorDeserializer.kt index c79fb9f..e07b226 100644 --- a/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorDeserializer.kt +++ b/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorDeserializer.kt @@ -30,10 +30,11 @@ open class ObjectDescriptorDeserializer() : StdDeserializer(Ob } else { val multiplicity = Multiplicity.valueOf( property["target"].asText()) + val owner = property["owner"].asBoolean() val cascade: Cascade? = null if ( property.has("cascade")) Cascade.valueOf( property["cascade"].asText()) - properties.add(RelationDescriptor(propertyName, property["target"].asText(), multiplicity, cascade, property["inverse"].asText())) + properties.add(RelationDescriptor(propertyName, property["target"].asText(), multiplicity, cascade, property["inverse"].asText(), owner)) } } diff --git a/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorSerializer.kt b/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorSerializer.kt index d71bc63..cc6dc5f 100644 --- a/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorSerializer.kt +++ b/src/main/kotlin/org/sirius/dorm/model/json/ObjectDescriptorSerializer.kt @@ -27,6 +27,7 @@ open class ObjectDescriptorSerializer : StdSerializer(ObjectDe else { jsonGenerator.writeStringField("target", property.asRelation().target) jsonGenerator.writeStringField("inverse", property.asRelation().inverse) + jsonGenerator.writeBooleanField("owner", property.asRelation().owner) if (property.asRelation().cascade !== null) jsonGenerator.writeStringField("cascade", property.asRelation().cascade!!.name) jsonGenerator.writeObjectField("multiplicity", property.asRelation().multiplicity.name) diff --git a/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt b/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt index b38f8bc..ed19a3b 100644 --- a/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/MultiValuedRelation.kt @@ -51,10 +51,10 @@ class MultiValuedRelation(relation: RelationDescriptor<*>, status: Status, val o override fun isLoaded() : Boolean { return objects !== null } - override fun addInverse(element: DataObject) { + override fun addedToInverse(element: DataObject) { this.objects!!.add(element) } - override fun removeInverse(element: DataObject) { + override fun removedFromInverse(element: DataObject) { this.objects!!.remove(element) } @@ -112,7 +112,7 @@ class MultiValuedRelation(relation: RelationDescriptor<*>, status: Status, val o val inverse = inverseRelation(element) if ( inverse !== null) - inverse.addInverse(obj) + inverse.addedToInverse(obj) else TransactionState.current().addRedo(element.id, relation.inverseRelation!!.name, AddToRelation(this.obj)) @@ -138,7 +138,7 @@ class MultiValuedRelation(relation: RelationDescriptor<*>, status: Status, val o val inverse = inverseRelation(element) if ( inverse !== null) - inverse.removeInverse(element) + inverse.removedFromInverse(element) else TransactionState.current().addRedo(element.id, relation.inverseRelation!!.name, RemoveFromRelation(this.obj)) diff --git a/src/main/kotlin/org/sirius/dorm/object/Relation.kt b/src/main/kotlin/org/sirius/dorm/object/Relation.kt index 6dc6afa..f16f8da 100644 --- a/src/main/kotlin/org/sirius/dorm/object/Relation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/Relation.kt @@ -42,6 +42,6 @@ abstract class Relation(val relation: RelationDescriptor<*>, val targetDescripto // abstract - abstract fun addInverse(element: DataObject) - abstract fun removeInverse(element: DataObject) + abstract fun addedToInverse(element: DataObject) + abstract fun removedFromInverse(element: DataObject) } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt b/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt index 279a115..4675113 100644 --- a/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt +++ b/src/main/kotlin/org/sirius/dorm/object/SingleValuedRelation.kt @@ -79,7 +79,7 @@ class SingleValuedRelation(relation: RelationDescriptor<*>, status: Status, val if ( value !== this.target) { var inverse = inverseRelation(this.target) if ( inverse !== null) - inverse.removeInverse(this.obj) + inverse.removedFromInverse(this.obj) else if ( this.target !== null) TransactionState.current().addRedo(this.target!!.id, relation.inverseRelation!!.name, RemoveFromRelation(this.obj)) @@ -88,7 +88,7 @@ class SingleValuedRelation(relation: RelationDescriptor<*>, status: Status, val if ( this.target !== null) { inverse = inverseRelation(this.target) if ( inverse !== null) - inverse.addInverse(this.obj) + inverse.addedToInverse(this.obj) else TransactionState.current().addRedo(this.target!!.id, relation.inverseRelation!!.name, AddToRelation(this.obj)) } @@ -100,10 +100,10 @@ class SingleValuedRelation(relation: RelationDescriptor<*>, status: Status, val else return false } - override fun addInverse(element: DataObject) { + override fun addedToInverse(element: DataObject) { this.target = element } - override fun removeInverse(element: DataObject) { + override fun removedFromInverse(element: DataObject) { this.target = null } } \ No newline at end of file diff --git a/src/main/kotlin/org/sirius/dorm/persistence/ObjectReader.kt b/src/main/kotlin/org/sirius/dorm/persistence/ObjectReader.kt index 5f4812e..00c88ea 100644 --- a/src/main/kotlin/org/sirius/dorm/persistence/ObjectReader.kt +++ b/src/main/kotlin/org/sirius/dorm/persistence/ObjectReader.kt @@ -33,7 +33,7 @@ class ObjectReader(descriptor: ObjectDescriptor, objectManager: ObjectManager) { // companion companion object { - fun valueReader(clazz: Class) : (attribute: PropertyEntity) -> Any { + fun valueReader(clazz: Class) : (attribute: PropertyEntity) -> Any { return when (clazz) { Boolean::class.javaObjectType -> { attribute: PropertyEntity -> attribute.intValue == 1 } diff --git a/src/main/kotlin/org/sirius/dorm/persistence/ObjectWriter.kt b/src/main/kotlin/org/sirius/dorm/persistence/ObjectWriter.kt index 55e74cb..4c4da4f 100644 --- a/src/main/kotlin/org/sirius/dorm/persistence/ObjectWriter.kt +++ b/src/main/kotlin/org/sirius/dorm/persistence/ObjectWriter.kt @@ -33,15 +33,13 @@ class ObjectWriter(private val descriptor: ObjectDescriptor) { var i = 1 for ( writer in writer) { val propertyDescriptor = descriptor.properties[i] - val attribute = PropertyEntity(obj.entity!!, propertyDescriptor.name, descriptor.name, "", 0, 0.0) + val property = PropertyEntity(obj.entity!!, propertyDescriptor.name, descriptor.name, "", 0, 0.0) - // set entity, we may need it for flushing relations + obj.values[i].property = property - obj.values[i].property = attribute + writer(state, obj, i++, property) - writer(state, obj, i++, attribute) - - entityManager.persist(attribute) + entityManager.persist(property) //obj.entity!!.properties.add(attribute) } diff --git a/src/main/kotlin/org/sirius/dorm/query/ObjectPath.kt b/src/main/kotlin/org/sirius/dorm/query/ObjectPath.kt index 8acbee1..39680bc 100644 --- a/src/main/kotlin/org/sirius/dorm/query/ObjectPath.kt +++ b/src/main/kotlin/org/sirius/dorm/query/ObjectPath.kt @@ -17,7 +17,7 @@ abstract class ObjectPath(val parent : ObjectPath? = null) { abstract fun expression(root: Root): Path - abstract fun type() : Class + abstract fun type() : Class open fun attributeName() : String { throw Error("abstract") diff --git a/src/main/kotlin/org/sirius/dorm/query/PropertyPath.kt b/src/main/kotlin/org/sirius/dorm/query/PropertyPath.kt index 79bfe73..180dca8 100644 --- a/src/main/kotlin/org/sirius/dorm/query/PropertyPath.kt +++ b/src/main/kotlin/org/sirius/dorm/query/PropertyPath.kt @@ -23,7 +23,7 @@ class PropertyPath(parent: ObjectPath, val property: PropertyDescriptor) : return property.name } - override fun type() : Class { + override fun type() : Class { return property.asAttribute().type.baseType } diff --git a/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt b/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt index f079acc..474a7bb 100644 --- a/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt +++ b/src/main/kotlin/org/sirius/dorm/transaction/TransactionState.kt @@ -34,13 +34,13 @@ abstract class UpdateRelation { class AddToRelation(val obj: DataObject) : UpdateRelation() { override fun execute(relation: Relation) { - relation.addInverse(obj) + relation.addedToInverse(obj) } } class RemoveFromRelation(val obj: DataObject) : UpdateRelation() { override fun execute(relation: Relation) { - relation.removeInverse(obj) + relation.removedFromInverse(obj) } } class Redo() { diff --git a/src/test/kotlin/org/sirius/dorm/AbstractTest.kt b/src/test/kotlin/org/sirius/dorm/AbstractTest.kt index ab7ef49..5eb88b5 100644 --- a/src/test/kotlin/org/sirius/dorm/AbstractTest.kt +++ b/src/test/kotlin/org/sirius/dorm/AbstractTest.kt @@ -17,6 +17,8 @@ import org.sirius.common.tracer.trace.ConsoleTrace import org.sirius.common.type.base.* import org.sirius.dorm.model.Multiplicity import org.sirius.dorm.model.ObjectDescriptor +import org.sirius.dorm.model.attribute +import org.sirius.dorm.model.relation import org.sirius.dorm.`object`.DataObject import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest @@ -170,21 +172,21 @@ class AbstractTest { val intType = int().greaterEqual(0) objectManager.type("person") - .attribute("name", stringType) - .attribute("age", intType) + .property(attribute("name").type(stringType)) + .property(attribute("age").type(intType)) // relations - .relation("father", "person", Multiplicity.ZERO_OR_ONE, "children") - .relation("children", "person", Multiplicity.ZERO_OR_MANY) + .property(relation("father").target("person").multiplicity(Multiplicity.ZERO_OR_ONE).inverse("children")) + .property(relation("children").target("person").multiplicity(Multiplicity.ZERO_OR_MANY).inverse("father")) - .attribute("boolean", boolean()) - .attribute("string", string()) - .attribute("short", short()) - .attribute("int", int()) - .attribute("long", long()) - .attribute("float", float()) - .attribute("double", double()) + .property(attribute("boolean").type(boolean())) + .property(attribute("string").type(string())) + .property(attribute("short").type(short())) + .property(attribute("int").type(int())) + .property(attribute("long").type(long())) + .property(attribute("float").type(float())) + .property(attribute("double").type(double())) .register() } diff --git a/src/test/kotlin/org/sirius/dorm/DORMBenchmark.kt b/src/test/kotlin/org/sirius/dorm/DORMBenchmark.kt index 51a0436..2a4a9ff 100644 --- a/src/test/kotlin/org/sirius/dorm/DORMBenchmark.kt +++ b/src/test/kotlin/org/sirius/dorm/DORMBenchmark.kt @@ -10,8 +10,8 @@ import jakarta.persistence.* import jakarta.persistence.criteria.CriteriaBuilder 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.model.attribute @Entity @Table(name="HOBBY") @@ -109,7 +109,7 @@ internal class DORMBenchmark : AbstractTest() { withTransaction { objectManager.type("small-person") - .attribute("name", string()) + .property(attribute("name").type(string())) .register() } diff --git a/src/test/kotlin/org/sirius/dorm/RelationTests.kt b/src/test/kotlin/org/sirius/dorm/RelationTests.kt index 414c233..7b09d96 100644 --- a/src/test/kotlin/org/sirius/dorm/RelationTests.kt +++ b/src/test/kotlin/org/sirius/dorm/RelationTests.kt @@ -8,9 +8,7 @@ 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.Cascade -import org.sirius.dorm.model.Multiplicity -import org.sirius.dorm.model.ObjectDescriptor +import org.sirius.dorm.model.* import org.sirius.dorm.`object`.MultiValuedRelation import org.sirius.dorm.`object`.Relation import org.sirius.dorm.`object`.SingleValuedRelation @@ -58,9 +56,9 @@ class RelationTests: AbstractTest() { fun testSynchronization() { withTransaction { objectManager.type("pp") - .attribute("name", string()) - .relation("children", "pp", Multiplicity.ZERO_OR_MANY, "father") - .relation("father", "pp", Multiplicity.ZERO_OR_ONE, "children") + .property(attribute("name").type(string())) + .property(relation("children").target("pp").multiplicity(Multiplicity.ZERO_OR_MANY).inverse("father")) + .property(relation("father").target("pp").multiplicity(Multiplicity.ZERO_OR_ONE).inverse("children")) .register() } @@ -80,19 +78,22 @@ class RelationTests: AbstractTest() { val child = objectManager.create(descriptor) + child["name"] = "Nika" + childId = child.id person.relation("children").add(child) - } - printTables() + printTables() // expect 1 relation // reread withTransaction { val child = objectManager.findById(descriptor, childId)!! + assert(child["father"] !== null) + child["father"] = null // load father and check if the relation is empty @@ -102,7 +103,7 @@ class RelationTests: AbstractTest() { assertEquals(0, father.relation("children").size) } - printTables() + printTables() // expect empty relation // other way round @@ -118,6 +119,8 @@ class RelationTests: AbstractTest() { assert(childFather == father) } + + printTables() // expect 1 relation } @Test @@ -126,9 +129,9 @@ class RelationTests: AbstractTest() { withTransaction { objectManager.type("p") - .attribute("name", string()) - .relation("children", "p", Multiplicity.ZERO_OR_MANY, "father") - .relation("father", "p", Multiplicity.ZERO_OR_ONE, "children") + .property(attribute("name").type(string())) + .property(relation("children").target("p").multiplicity(Multiplicity.ZERO_OR_MANY).inverse("father").owner()) + .property(relation("father").target("p").multiplicity(Multiplicity.ZERO_OR_ONE).inverse("children")) .register() } @@ -210,13 +213,13 @@ class RelationTests: AbstractTest() { withTransaction { objectManager.type("product") - .attribute("name", string()) - .relation("parts", "part", Multiplicity.ZERO_OR_MANY, "product", Cascade.DELETE) + .property(attribute("name").type(string())) + .property(relation("parts").target("part").multiplicity(Multiplicity.ZERO_OR_MANY).inverse("product").cascade(Cascade.DELETE).owner()) .register() objectManager.type("part") - .attribute("name", string()) - .relation("product", "product", Multiplicity.ONE) + .property(attribute("name").type(string())) + .property(relation("product").target("product").inverse("parts").multiplicity(Multiplicity.ONE)) .register() } @@ -302,9 +305,9 @@ class RelationTests: AbstractTest() { withTransaction { objectManager.type("p1") - .attribute("name", string()) - .relation("parent", "p1", Multiplicity.ZERO_OR_ONE, "children") - .relation("children", "p1", Multiplicity.ZERO_OR_MANY, "parent") + .property(attribute("name").type(string())) + .property(relation("parent").target("p1").multiplicity(Multiplicity.ZERO_OR_ONE).inverse("children").owner()) + .property(relation("children").target("p1").multiplicity(Multiplicity.ZERO_OR_MANY).inverse("parent")) .register() }