mybatisplus @TableName 注解中 excludeProperty 赋值问题

2023-10-31 11:23:02 +08:00
 cMoon

想通过 excludeProperty 来排除父类中的字段,但是不想硬编码写死,就写了个静态方法获取父类中的所有字段名, excludeProperty 通过调用这个静态方法赋值,但是提示 Attribute value must be constant.

百度后了解到注解中属性的赋值只能是常量,这里有没有什么曲线救国的方法,比如使用 SpEL 表达式之类的(SpEL 不太会用,编译虽然能过但没有正确排除父类字段,不清楚是语法错了还是本身就不能解决这个问题),还是说已经是死局了只能硬编码.

1403 次点击
所在节点    Java
13 条回复
Jrue0011
2023-10-31 11:36:46 +08:00
可以是可以...

一种方式是改 Mybatis-Plus 的 TableInfoHelper 代码实现对 excludeProperty 中 SPEL 的支持,并想办法让所有依赖 TableInfoHelper 的地方能用上新的实现(改源码重新打包、运行时动态增强/替换之类的)

另一种方式是既然你需求都是静态的,那甚至没必要用 SPEL ,自己写个类似 lombok 的注解处理器修改 excludeProperty
cMoon
2023-10-31 12:12:56 +08:00
@Jrue0011 #1 要自己实现的话就算了,为了一碟醋包一盘饺子😂 实在没办法我就老老实实写 sql 了
RedBeanIce
2023-10-31 14:21:43 +08:00
我不理解,,请问你可以再描述一下你的根本问题呢,请不要问 AB 问题。
因为 A 问题,问了 B 问题。

@tableName 描述的就是数据库的一个单表,为什么会存在父类的情况呢。
除非是公共字段,,,但是公共字段就是每张表都存在的。
cMoon
2023-10-31 14:46:04 +08:00
@RedBeanIce #3
目前有 3 张表 a,b,c
a 是主表, b,c 可以看成是 a 表的扩充字段.部分情况下 a 表的字段就够了,部分情况需要用到 b 或者 c 的字段.( b,c 都需要和 a 关联查询,不会查单表)
我想着用同一个实体接收数据的话无用的字段太多,就把 b,c 的实体类继承了 a.
这样就可以直接用 b,c 的实体类接收数据.

我也没啥设计经验,前两天本就想发帖问问的,但尝试做了下之后除了不能使用 mp 默认提供的方法也没发现啥弊端就继续这样做了
win301
2023-10-31 16:44:08 +08:00
绝大部分开发者不会用你这个思路来使用 ORM 框架,所以也不会碰到你的问题
说个正常的或者通常情况下使用 ORM 框架的思路
给这 3 个表分别建立 3 个 entity ,3 个 mapper ,然后你再任意 serviceImpl 类里,随意封装数据结构即可
就是有几百个表都有你说的情况,也都按照这个模式来做,这样即便某些表修改了字段增删了字段,在代码层面的改动会非常小,也很容易改
cMoon
2023-10-31 17:22:19 +08:00
@win301 #5
我只是在这基础上多了继承关系,这样在增删改查的时候可以少一步拆分或组装实体类的步骤
至于增删了字段,相比原来的模式也就多了需要改动插入和更新语句

这是我目前的理解,我认为还是利大于弊的
dadebucuo
2023-10-31 17:47:22 +08:00
不建议对 entity 进行继承操作, 可以定义公共字段的 get, set 方法作为接口, 子类来实现
wolfie
2023-10-31 18:06:32 +08:00
bytebuddy 运行时重新定义。

公共的数据库实体父类,就应该在父类主动 exclude 。
DreamSpace
2023-10-31 20:27:21 +08:00
@cMoon 能明白 op 的意思,我提一点个人看法。
其实你的 B 实体看似和 A 相似,但却有不同的业务意义,这时他们就是两个独立的实体,并不具有继承关系。
比如用于页面显示的 VO 和数据库层的 DO ,DO 中的 createTime 是 Date 类型,在 VO 中却是个 formatString 。
DO 不出 service ,VO 不进 dao ,实体变换/组装在 service 或者构造器中完成,嫌麻烦也可以用 mapstruct 之类的工具辅助。
DreamSpace
2023-10-31 20:39:09 +08:00
关于主楼提到的问题,注解和普通的 property 是一类东西,编译后就已经固定下来了,但你写的静态方法是必须运行时才会执行的,所以只能硬编码。回到硬编码的话,直接复制父类的属性贴在子类上然后打注解也许更快。
win301
2023-10-31 21:26:17 +08:00
@cMoon 你这相当于是面向数据库编程了,这 b 表和 c 表如果以后还会被其他表关联,你打算怎么做?继续通过继承,然后继续 excludeProperty 无关字段?(假设 excludeProperty 能实现你的想法),建议你复习一下或者重新学习一下面向对象编程有五个基本原则。
cMoon
2023-10-31 22:17:50 +08:00
@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 的实体类,之后就可以根据实际类型去处理不同的业务

直接复制父类的属性贴在子类上然后打注解也许更快。 --- 如果没有更好的方法了我是准备这么做了
Aresxue
2023-11-01 11:24:57 +08:00
瞄了眼源码,除非改源码实现不了。

第一 MP 功能确实不够强大,其实对于 excludeProperty 本来应该是提供 @JsonIgnore 、 @JsonIgnoreParentProperties 这样单独的注解去实现的,同时还要留给外界一些扩展点类似 jackson 的 BeanSerializerModifier 去做自定义。
第二虽然知道很多小项目怎么写都可以顺手就行,但是 DO 一把梭随便继承这种坏习惯能避免还是尽量避免,至于为啥不用继承这几乎是一种共识了,耦合度 继承 > 接口 > 组合。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/987024

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX