想通过 excludeProperty 来排除父类中的字段,但是不想硬编码写死,就写了个静态方法获取父类中的所有字段名, excludeProperty 通过调用这个静态方法赋值,但是提示 Attribute value must be constant.
百度后了解到注解中属性的赋值只能是常量,这里有没有什么曲线救国的方法,比如使用 SpEL 表达式之类的(SpEL 不太会用,编译虽然能过但没有正确排除父类字段,不清楚是语法错了还是本身就不能解决这个问题),还是说已经是死局了只能硬编码.
1
Jrue0011 2023-10-31 11:36:46 +08:00
可以是可以...
一种方式是改 Mybatis-Plus 的 TableInfoHelper 代码实现对 excludeProperty 中 SPEL 的支持,并想办法让所有依赖 TableInfoHelper 的地方能用上新的实现(改源码重新打包、运行时动态增强/替换之类的) 另一种方式是既然你需求都是静态的,那甚至没必要用 SPEL ,自己写个类似 lombok 的注解处理器修改 excludeProperty |
3
RedBeanIce 2023-10-31 14:21:43 +08:00
我不理解,,请问你可以再描述一下你的根本问题呢,请不要问 AB 问题。
因为 A 问题,问了 B 问题。 @tableName 描述的就是数据库的一个单表,为什么会存在父类的情况呢。 除非是公共字段,,,但是公共字段就是每张表都存在的。 |
4
cMoon OP @RedBeanIce #3
目前有 3 张表 a,b,c a 是主表, b,c 可以看成是 a 表的扩充字段.部分情况下 a 表的字段就够了,部分情况需要用到 b 或者 c 的字段.( b,c 都需要和 a 关联查询,不会查单表) 我想着用同一个实体接收数据的话无用的字段太多,就把 b,c 的实体类继承了 a. 这样就可以直接用 b,c 的实体类接收数据. 我也没啥设计经验,前两天本就想发帖问问的,但尝试做了下之后除了不能使用 mp 默认提供的方法也没发现啥弊端就继续这样做了 |
5
win301 2023-10-31 16:44:08 +08:00
绝大部分开发者不会用你这个思路来使用 ORM 框架,所以也不会碰到你的问题
说个正常的或者通常情况下使用 ORM 框架的思路 给这 3 个表分别建立 3 个 entity ,3 个 mapper ,然后你再任意 serviceImpl 类里,随意封装数据结构即可 就是有几百个表都有你说的情况,也都按照这个模式来做,这样即便某些表修改了字段增删了字段,在代码层面的改动会非常小,也很容易改 |
6
cMoon OP @win301 #5
我只是在这基础上多了继承关系,这样在增删改查的时候可以少一步拆分或组装实体类的步骤 至于增删了字段,相比原来的模式也就多了需要改动插入和更新语句 这是我目前的理解,我认为还是利大于弊的 |
7
dadebucuo 2023-10-31 17:47:22 +08:00
不建议对 entity 进行继承操作, 可以定义公共字段的 get, set 方法作为接口, 子类来实现
|
8
wolfie 2023-10-31 18:06:32 +08:00 via Android
bytebuddy 运行时重新定义。
公共的数据库实体父类,就应该在父类主动 exclude 。 |
9
DreamSpace 2023-10-31 20:27:21 +08:00 via Android
@cMoon 能明白 op 的意思,我提一点个人看法。
其实你的 B 实体看似和 A 相似,但却有不同的业务意义,这时他们就是两个独立的实体,并不具有继承关系。 比如用于页面显示的 VO 和数据库层的 DO ,DO 中的 createTime 是 Date 类型,在 VO 中却是个 formatString 。 DO 不出 service ,VO 不进 dao ,实体变换/组装在 service 或者构造器中完成,嫌麻烦也可以用 mapstruct 之类的工具辅助。 |
10
DreamSpace 2023-10-31 20:39:09 +08:00 via Android
关于主楼提到的问题,注解和普通的 property 是一类东西,编译后就已经固定下来了,但你写的静态方法是必须运行时才会执行的,所以只能硬编码。回到硬编码的话,直接复制父类的属性贴在子类上然后打注解也许更快。
|
11
win301 2023-10-31 21:26:17 +08:00
@cMoon 你这相当于是面向数据库编程了,这 b 表和 c 表如果以后还会被其他表关联,你打算怎么做?继续通过继承,然后继续 excludeProperty 无关字段?(假设 excludeProperty 能实现你的想法),建议你复习一下或者重新学习一下面向对象编程有五个基本原则。
|
12
cMoon OP @win301 #11
b ,c 是 a 的扩充字段不会关联其他表,但 a 可能会继续关联新的 d ,e 表 @DreamSpace #9 我就用优惠券举个例子吧 表 a 是通用的优惠券表,包含优惠金额,有效期限等 表 b ,c 是特殊的优惠券表,像某些券会指定哪些商家可以用,就会拓展一些可用商家 id 的字段 a ,b ,c 本质都是优惠券,只不过 a 没有额外字段的需求,能满足大部分优惠券的场景,b ,c 是为了剩下一小部分的场景做了单独的处理。 b ,c 显式地继承了 a ,也可以认为 a 继承了 a 本身,a 不仅是一个实体,也作为了一层抽象。 优惠券新增方法的参数声明可以声明成 a ,这样传参也能传入 b ,c 的实体类,之后就可以根据实际类型去处理不同的业务 直接复制父类的属性贴在子类上然后打注解也许更快。 --- 如果没有更好的方法了我是准备这么做了 |
13
Aresxue 2023-11-01 11:24:57 +08:00
瞄了眼源码,除非改源码实现不了。
第一 MP 功能确实不够强大,其实对于 excludeProperty 本来应该是提供 @JsonIgnore 、 @JsonIgnoreParentProperties 这样单独的注解去实现的,同时还要留给外界一些扩展点类似 jackson 的 BeanSerializerModifier 去做自定义。 第二虽然知道很多小项目怎么写都可以顺手就行,但是 DO 一把梭随便继承这种坏习惯能避免还是尽量避免,至于为啥不用继承这几乎是一种共识了,耦合度 继承 > 接口 > 组合。 |