Skip to content

Commit 0e2a48e

Browse files
committed
orm支持通过回调动态获得对象的关联关系
1 parent f068824 commit 0e2a48e

File tree

9 files changed

+465
-81
lines changed

9 files changed

+465
-81
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package net.jkcode.jkmvc.orm
2+
3+
import java.util.*
4+
5+
/**
6+
* 通过回调动态获得对象的关联关系的元数据
7+
* 回调可以是rpc
8+
*
9+
* @author shijianhang<[email protected]>
10+
* @date 2020-7-9 7:13 PM
11+
*/
12+
class CbRelationMeta<M:IOrm, K, R> (
13+
override val hasMany: Boolean, // 是否一对多
14+
override val pkGetter: (M)->K, // 主模型的主键的getter
15+
override val fkGetter: (R)->K, // 从对象的外键的getter
16+
override val relatedSupplier:(List<K>) -> List<R> // 批量获取关联对象的回调
17+
) : ICbRelationMeta<M, K, R> {
18+
19+
/**
20+
* 关系名
21+
*/
22+
override lateinit var name: String
23+
24+
/**
25+
* 查询关联对象
26+
* 自动根据关联关系,来构建查询条件
27+
*
28+
* @param item Orm对象
29+
* @return
30+
*/
31+
override fun findRelated(item: M): R?{
32+
return findAllRelated(item).firstOrNull()
33+
}
34+
35+
/**
36+
* 查询关联对象
37+
* 自动根据关联关系,来构建查询条件
38+
*
39+
* @param item Orm对象
40+
* @return
41+
*/
42+
override fun findAllRelated(item: M): List<R>{
43+
val pk = pkGetter.invoke(item)
44+
return relatedSupplier.invoke(listOf(pk))
45+
}
46+
47+
/**
48+
* 查询关联对象
49+
* 自动根据关联关系,来构建查询条件
50+
*
51+
* @param items Orm列表
52+
* @return
53+
*/
54+
override fun findAllRelated(items: Collection<M>): List<R>{
55+
val pks = items.map(pkGetter)
56+
return relatedSupplier.invoke(pks)
57+
}
58+
59+
60+
/**
61+
* 设置关系的属性值
62+
*
63+
* @param items 本模型对象
64+
* @param relatedItems 关联模型对象
65+
*/
66+
override fun setRelationProp(items: List<M>, relatedItems: List<R>) {
67+
if(items.isEmpty() || relatedItems.isEmpty())
68+
return
69+
70+
// 设置关联属性 -- 双循环匹配主外键
71+
for (item in items) { // 遍历每个源对象,收集关联对象
72+
for (relatedItem in relatedItems) { // 遍历每个关联对象,进行匹配
73+
// 关系的匹配: 本表键=关联表键
74+
val pk = pkGetter.invoke(item) // 本表键
75+
val fk = fkGetter.invoke(relatedItem) // 关联表键
76+
if (pk != null && fk != null && pk.equals(fk)) {
77+
if(hasMany){ // hasMany关联对象是list
78+
val myRelated = item.getOrPut(name){
79+
LinkedList<Any?>()
80+
} as LinkedList<Any?>
81+
myRelated.add(relatedItem)
82+
}else{ // 其他关联对象是单个对象
83+
item[name] = relatedItem
84+
}
85+
86+
}
87+
}
88+
}
89+
90+
// 清空列表
91+
(relatedItems as MutableList).clear()
92+
}
93+
}

jkmvc-orm/src/main/kotlin/net/jkcode/jkmvc/orm/DbKey.kt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,32 @@ class DbKey<T> {
111111
}
112112
}
113113

114+
/**
115+
* Returns `true` if at least one element matches the given [predicate].
116+
*
117+
* @sample samples.collections.Collections.Aggregates.anyWithPredicate
118+
*/
119+
public inline fun <S> anyColumnWith(o: DbKey<S>, predicate: (T, S) -> Boolean): Boolean {
120+
forEachColumnWith(o){ col1: T, col2: S, i:Int ->
121+
if (predicate(col1, col2))
122+
return true
123+
}
124+
return false
125+
}
126+
127+
/**
128+
* Returns `true` if all elements match the given [predicate].
129+
*
130+
* @sample samples.collections.Collections.Aggregates.all
131+
*/
132+
public inline fun <S> allColumnWith(o: DbKey<S>, predicate: (T, S) -> Boolean): Boolean {
133+
forEachColumnWith(o){ col1: T, col2: S, i:Int ->
134+
if (!predicate(col1, col2))
135+
return false
136+
}
137+
return true
138+
}
139+
114140
/**
115141
* 访问字段
116142
* @param i
@@ -121,7 +147,7 @@ class DbKey<T> {
121147
}
122148

123149
/**
124-
* 检查相等
150+
* 检查元素值相等
125151
* 在 OrmQueryBuilder.setHasManyProp() 中用于匹配一对多的外键来设置关联属性
126152
*/
127153
public override fun equals(o: Any?): Boolean {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package net.jkcode.jkmvc.orm
2+
3+
/**
4+
* 通过回调动态获得对象的关联关系的元数据
5+
* 回调可以是rpc
6+
*
7+
* @author shijianhang<[email protected]>
8+
* @date 2020-7-9 7:13 PM
9+
*/
10+
interface ICbRelationMeta<M : IOrm, K, R> {
11+
12+
/**
13+
* 关系名
14+
*/
15+
val name: String
16+
17+
/**
18+
* 是否一对多
19+
*/
20+
val hasMany: Boolean
21+
22+
/**
23+
* 主模型的主键的getter
24+
*/
25+
val pkGetter: (M)->K
26+
27+
/**
28+
* 从对象的外键的getter
29+
*/
30+
val fkGetter: (R)->K
31+
32+
/**
33+
* 批量获取关联对象的回调
34+
*/
35+
val relatedSupplier:(List<K>) -> List<R>
36+
37+
/**
38+
* 查询关联对象
39+
* 自动根据关联关系,来构建查询条件
40+
*
41+
* @param item Orm对象
42+
* @return
43+
*/
44+
fun findRelated(item: M): R?
45+
46+
/**
47+
* 查询关联对象
48+
* 自动根据关联关系,来构建查询条件
49+
*
50+
* @param orm Orm对象或列表
51+
* @return
52+
*/
53+
fun findAllRelated(orm: Any): List<R>{
54+
return when(orm){
55+
is IOrm -> findAllRelated(orm)
56+
is Collection<*> -> findAllRelated(orm as Collection<M>)
57+
else -> throw IllegalArgumentException("对relation.findAllRelated(参数)方法,其参数必须是Orm对象或Orm列表")
58+
}
59+
}
60+
61+
/**
62+
* 查询关联对象
63+
* 自动根据关联关系,来构建查询条件
64+
*
65+
* @param item Orm对象
66+
* @return
67+
*/
68+
fun findAllRelated(item: M): List<R>
69+
70+
/**
71+
* 查询关联对象
72+
* 自动根据关联关系,来构建查询条件
73+
*
74+
* @param items Orm列表
75+
* @return
76+
*/
77+
fun findAllRelated(items: Collection<M>): List<R>
78+
79+
/**
80+
* 设置关系的属性值
81+
*
82+
* @param items 本模型对象
83+
* @param relatedItems 关联模型对象
84+
*/
85+
fun setRelationProp(items: List<M>, relatedItems: List<R>)
86+
}

jkmvc-orm/src/main/kotlin/net/jkcode/jkmvc/orm/IOrmMeta.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,41 @@ interface IOrmMeta {
957957
return hasManyThrough(name, relatedModel, DbKeyNames(foreignKey), DbKeyNames(primaryKey), middleTable, DbKeyNames(farForeignKey), DbKeyNames(farPrimaryKey), conditions)
958958
}
959959

960+
/********************************* 通过回调动态获得对象的关联关系 **************************************/
961+
/**
962+
* 是否有某个回调的关联关系
963+
* @param name
964+
* @return
965+
*/
966+
fun hasCbRelation(name: String): Boolean
967+
968+
/**
969+
* 获得某个回调的关联关系
970+
* @param name
971+
* @return
972+
*/
973+
fun getCbRelation(name: String): ICbRelationMeta<out IOrm, *, *>?
974+
975+
/**
976+
* 设置通过回调动态获得对象的关联关系(has one)
977+
* @param name 字段名
978+
* @param pkGetter 当前模型的主键的getter
979+
* @param fkGetter 关联对象的外键的getter
980+
* @param relatedSupplier 批量获取关联对象的回调
981+
* @return
982+
*/
983+
fun <M:IOrm, K, R> cbHasOne(name: String, pkGetter: (M)->K, fkGetter: (R)->K, relatedSupplier:(List<K>) -> List<R>): IOrmMeta
984+
985+
/**
986+
* 设置通过回调动态获得对象的关联关系(has many)
987+
* @param name 字段名
988+
* @param pkGetter 当前模型的主键的getter
989+
* @param fkGetter 关联对象的外键的getter
990+
* @param relatedSupplier 批量获取关联对象的回调
991+
* @return
992+
*/
993+
fun <M:IOrm, K, R> cbHasMany(name: String, pkGetter: (M)->K, fkGetter: (R)->K, relatedSupplier:(List<K>) -> List<R>): IOrmMeta
994+
960995
/********************************* xstream **************************************/
961996
/**
962997
* 初始化xstream

jkmvc-orm/src/main/kotlin/net/jkcode/jkmvc/orm/IRelationMeta.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import kotlin.reflect.KClass
1616
*/
1717
interface IRelationMeta {
1818

19+
/**
20+
* 关系名
21+
*/
22+
val name: String
23+
1924
/**
2025
* 源模型元数据
2126
*/
@@ -158,4 +163,11 @@ interface IRelationMeta {
158163
*/
159164
fun queryRelated(items: Collection<out IOrm>): OrmQueryBuilder
160165

166+
/**
167+
* 设置关系的属性值
168+
*
169+
* @param items 本模型对象
170+
* @param relatedItems 关联模型对象
171+
*/
172+
fun setRelationProp(items: List<IOrm>, relatedItems: List<IOrm>)
161173
}

0 commit comments

Comments
 (0)