diff --git a/src/main/kotlin/com/quasar/dorm/ObjectManager.kt b/src/main/kotlin/com/quasar/dorm/ObjectManager.kt index 315c39a..2e2a618 100644 --- a/src/main/kotlin/com/quasar/dorm/ObjectManager.kt +++ b/src/main/kotlin/com/quasar/dorm/ObjectManager.kt @@ -18,6 +18,7 @@ import com.quasar.dorm.type.base.int import jakarta.persistence.EntityManager import jakarta.persistence.PersistenceContext import org.antlr.v4.runtime.ANTLRInputStream +import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.RecognitionException import org.springframework.beans.factory.annotation.Autowired @@ -143,7 +144,7 @@ class ObjectManager() { } fun query(query: String, resultType: Class = DataObject::class.java as Class) : Query { - val tokenStream = CommonTokenStream(OQLLexer(ANTLRInputStream(query))) + val tokenStream = CommonTokenStream(OQLLexer(CharStreams.fromString(query))) val parser = OQLParser(tokenStream) diff --git a/src/main/kotlin/com/quasar/dorm/persistence/DataObjectMapper.kt b/src/main/kotlin/com/quasar/dorm/persistence/DataObjectMapper.kt index 2895064..aa1c8c3 100644 --- a/src/main/kotlin/com/quasar/dorm/persistence/DataObjectMapper.kt +++ b/src/main/kotlin/com/quasar/dorm/persistence/DataObjectMapper.kt @@ -16,7 +16,9 @@ import com.quasar.dorm.transaction.TransactionState import com.fasterxml.jackson.databind.ObjectMapper import jakarta.persistence.EntityManager import jakarta.persistence.PersistenceContext +import jakarta.persistence.Query import jakarta.persistence.criteria.CriteriaBuilder +import jakarta.persistence.criteria.ParameterExpression import jakarta.persistence.criteria.Root import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -163,6 +165,93 @@ class ObjectWriter(private val descriptor: ObjectDescriptor) { } } +class AttributeUpdater(attribute: String, type: Class, entityManager: EntityManager) { + // instance data + + val entityId : ParameterExpression + val attributeId : ParameterExpression + val value : ParameterExpression + val updateAttribute : Query + + // init + + init { + val builder = entityManager.criteriaBuilder + + // delete attributes + + entityId = builder.parameter(Int::class.java) + attributeId = builder.parameter(String::class.java) + value = builder.parameter(type) + + val updateAttributeQuery = builder.createCriteriaUpdate(AttributeEntity::class.java) + val from = updateAttributeQuery.from(AttributeEntity::class.java) + + updateAttributeQuery.set(attribute, value); + + updateAttributeQuery.where(builder.and( + builder.equal(from.get("entity"), entityId), + builder.equal(from.get("attribute"), attributeId) + )) + + updateAttribute = entityManager.createQuery(updateAttributeQuery) + } + + // public + + fun update(entity: Int, attribute: String, value: T) { + updateAttribute + .setParameter(entityId, entity) + .setParameter(attributeId, attribute) + .setParameter(this.value, value) + .executeUpdate() + } +} + +class ObjectDeleter(entityManager: EntityManager) { + // instance data + + val attributeId : ParameterExpression + val entityId : ParameterExpression + val deleteAttribute : Query + val deleteEntity : Query + + // init + + init { + val builder = entityManager.criteriaBuilder + + // delete attributes + + attributeId = builder.parameter(Int::class.java) + + val deleteAttributeQuery = builder.createCriteriaDelete(AttributeEntity::class.java) + val from = deleteAttributeQuery.from(AttributeEntity::class.java) + + deleteAttributeQuery.where(builder.equal(from.get("entity"), attributeId)) + + deleteAttribute = entityManager.createQuery(deleteAttributeQuery) + + // delete entity + + entityId = builder.parameter(Int::class.java) + + val criteriaQueryEntity = builder.createCriteriaDelete(EntityEntity::class.java) + val fromEntity = criteriaQueryEntity.from(EntityEntity::class.java) + criteriaQueryEntity.where(builder.equal(fromEntity.get("id"), entityId)) + + deleteEntity = entityManager.createQuery(criteriaQueryEntity) + } + + // public + + fun delete(obj: DataObject) { + deleteAttribute.setParameter(attributeId, obj.getId()).executeUpdate() + deleteEntity.setParameter(entityId, obj.getId()).executeUpdate() + } +} + + @Component class DataObjectMapper() { // instance data @@ -176,13 +265,34 @@ class DataObjectMapper() { private val reader = ConcurrentHashMap() private val jsonReader = ConcurrentHashMap() private val writer = ConcurrentHashMap() + private val updater = ConcurrentHashMap>() + private val deleter = ConcurrentHashMap() // public fun update(obj: DataObject) { val builder: CriteriaBuilder = entityManager.criteriaBuilder - // update attributes + // new + + val properties = obj.type.properties + for ( index in 1..obj.values.size - 1) { + if ( obj.values[index] != obj.state!!.snapshot!![index]) { + val property = properties[index] + + when ( property.type.baseType) { + String::class.java -> updater4("stringValue", String::class.java).update(obj.getId(), property.name, obj.values[index] as String) + Integer::class.java -> updater4("intValue", Integer::class.java).update(obj.getId(), property.name, obj.values[index] as Integer) + Int::class.java -> updater4("intValue", Integer::class.java).update(obj.getId(), property.name, obj.values[index] as Integer) + + else -> { + throw Error("ouch") + } + } + } + } // for + + /* update attributes val criteriaQuery = builder.createQuery(AttributeEntity::class.java) val attributeEntity = criteriaQuery.from(AttributeEntity::class.java) @@ -203,6 +313,7 @@ class DataObjectMapper() { if ( obj.values[index] != obj.state!!.snapshot!![index]) writer.update(obj, index, attribute) } // for + */ // update entity @@ -219,28 +330,8 @@ class DataObjectMapper() { } fun delete(obj: DataObject) { - if ( obj.getId() < 0) - return - - val builder = entityManager.criteriaBuilder - - // delete attributes - - val criteriaQuery = builder.createCriteriaDelete(AttributeEntity::class.java) - val from = criteriaQuery.from(AttributeEntity::class.java) - - criteriaQuery.where(builder.equal(from.get("entity"), obj.getId())) - - entityManager.createQuery(criteriaQuery).executeUpdate() - - // delete entity - - val criteriaQueryEntity = builder.createCriteriaDelete(EntityEntity::class.java) - val fromEntity = criteriaQueryEntity.from(EntityEntity::class.java) - - criteriaQueryEntity.where(builder.equal(fromEntity.get("id"), obj.getId())) - - entityManager.createQuery(criteriaQueryEntity).executeUpdate() + if ( obj.getId() >= 0) + deleter4(obj.type).delete(obj) } fun create(obj: DataObject) { @@ -264,6 +355,7 @@ class DataObjectMapper() { val obj = jsonReader4(objectDescriptor).read(node) obj.setId(entity.id) // TODO ? + // set state state.register(ObjectState(obj, Status.MANAGED)) @@ -309,4 +401,12 @@ class DataObjectMapper() { private fun writer4(objectDescriptor: ObjectDescriptor) : ObjectWriter { return writer.getOrPut(objectDescriptor.name) { -> ObjectWriter(objectDescriptor) } } + + private fun updater4(attribute: String, type: Class) : AttributeUpdater { + return AttributeUpdater(attribute, type, entityManager)//TODO updater.getOrPut(objectDescriptor.name) { -> ObjectUpdater(objectDescriptor) } + } + + private fun deleter4(objectDescriptor: ObjectDescriptor) : ObjectDeleter { + return ObjectDeleter(entityManager)//TODO deleter.getOrPut(objectDescriptor.name) { -> ObjectDeleter(entityManager) } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/quasar/dorm/query/parser/AbstractQueryParser.kt b/src/main/kotlin/com/quasar/dorm/query/parser/AbstractQueryParser.kt index 8a5eb72..80f3ade 100644 --- a/src/main/kotlin/com/quasar/dorm/query/parser/AbstractQueryParser.kt +++ b/src/main/kotlin/com/quasar/dorm/query/parser/AbstractQueryParser.kt @@ -18,12 +18,11 @@ abstract class EXPR { } } - abstract class VALUE(val value: Any) : EXPR() { abstract fun resolve(query: Query) : Value } -class PARAMETER(private val name: String) : VALUE("null") { // TODO +class PARAMETER(private val name: String) : VALUE(name) { // override override fun resolve(query: Query) : Value { @@ -69,10 +68,10 @@ class SELECT() { val query = queryManager .create() // object query - .select(*select.map({path -> path.buildPath(alias)}).toTypedArray()) + .select(*select.map { path -> path.buildPath(alias) }.toTypedArray()) .from(from!!) - if ( where != null) + if ( where !== null) query.where(where!!.build(this, query)) return query as Query diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8fb762d..5d780c0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -8,5 +8,5 @@ spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy spring.sql.init.mode=always -spring.jpa.show-sql=false +spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file