+
Skip to content

Track and Provide Access to Changed Properties #525

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions buildSrc/src/main/kotlin/ktorm.publish.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ publishing {
id.set("brohacz")
name.set("Michal Brosig")
}
developer {
id.set("hc224")
name.set("hc224")
email.set("hc224@pm.me")
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions ktorm-core/src/main/kotlin/org/ktorm/entity/Entity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ public interface Entity<E : Entity<E>> : Serializable {
*/
public val properties: Map<String, Any?>

/**
* Return the immutable view of the original values for this entity's changed properties.
*
* Properties are set as changed when constructing an entity with non-default values or when setting a property.
* If the property is set to the same value it is still marked as changed.
*/
public val changedProperties: Map<String, Any?>

/**
* Update the property changes of this entity into the database and return the affected record number.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ internal class EntityImplementation(
@Transient var fromDatabase: Database? = fromDatabase
@Transient var fromTable: Table<*>? = fromTable
@Transient var parent: EntityImplementation? = parent
@Transient var changedProperties = LinkedHashSet<String>()
@Transient var changedProperties = LinkedHashMap<String, Any?>()

override fun invoke(proxy: Any, method: Method, args: Array<out Any>?): Any? {
return when (method.declaringClass.kotlin) {
Expand All @@ -54,6 +54,7 @@ internal class EntityImplementation(
when (method.name) {
"getEntityClass" -> this.entityClass
"getProperties" -> Collections.unmodifiableMap(this.values)
"getChangedProperties" -> Collections.unmodifiableMap(this.changedProperties)
"flushChanges" -> this.doFlushChanges()
"discardChanges" -> this.doDiscardChanges()
"delete" -> this.doDelete()
Expand Down Expand Up @@ -150,13 +151,15 @@ internal class EntityImplementation(
throw UnsupportedOperationException(msg)
}

// Map#putIfAbsent treats null as absent, but null is a valid entity value
if (!changedProperties.containsKey(name))
changedProperties[name] = this.values.getOrDefault(name, null)
values[name] = value
changedProperties.add(name)
}

private fun copy(): Entity<*> {
val entity = Entity.create(entityClass, parent, fromDatabase, fromTable)
entity.implementation.changedProperties.addAll(changedProperties)
entity.implementation.changedProperties.putAll(changedProperties)

for ((name, value) in values) {
if (value is Entity<*>) {
Expand Down Expand Up @@ -204,7 +207,7 @@ internal class EntityImplementation(
val javaClass = Class.forName(input.readUTF(), true, Thread.currentThread().contextClassLoader)
entityClass = javaClass.kotlin
values = input.readObject() as LinkedHashMap<String, Any?>
changedProperties = LinkedHashSet()
changedProperties = LinkedHashMap()
}

override fun equals(other: Any?): Boolean {
Expand Down
46 changes: 45 additions & 1 deletion ktorm-core/src/test/kotlin/org/ktorm/entity/EntityTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,50 @@ class EntityTest : BaseTest() {
assert(employee.job == "")
}

@Test
fun testEntityChangedPropertiesInitializer() {
val employee = Employee { name = "walter" }
println(employee)

assert(employee.changedProperties.size == 1)
assert(employee.changedProperties.contains("name"))
assert(employee.changedProperties["name"] == null)
}

@Test
fun testEntityChangedPropertiesSetter() {
val employee = Employee { }
println(employee)

val oldChangedPropertiesIsEmpty = employee.changedProperties.isEmpty()

employee.name = "walter"
println(employee)

assert(oldChangedPropertiesIsEmpty)
assert(employee.changedProperties.size == 1)
assert(employee.changedProperties.contains("name"))
assert(employee.changedProperties["name"] == null)
}

@Test
fun testEntityChangedPropertiesMultiple() {
val employee = Employee { }.copy()
println(employee)

val oldChangedPropertiesIsEmpty = employee.changedProperties.isEmpty()

employee.name = "walter"
println(employee)
employee.name = "vince"
println(employee)

assert(oldChangedPropertiesIsEmpty)
assert(employee.changedProperties.size == 1)
assert(employee.changedProperties.containsKey("name"))
assert(employee.changedProperties["name"] == null)
}

@Test
fun testDefaultMethod() {
for (method in Employee::class.java.methods) {
Expand Down Expand Up @@ -783,4 +827,4 @@ class EntityTest : BaseTest() {
assert(departmentTransient !== departmentAttached)
assert(departmentTransient.hashCode() == departmentAttached.hashCode())
}
}
}
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载