V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
cMoon
V2EX  ›  Java

mybatisplus @TableName 注解中 excludeProperty 赋值问题

  •  
  •   cMoon · Oct 31, 2023 · 3769 views
    This topic created in 914 days ago, the information mentioned may be changed or developed.

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

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

    13 replies    2023-11-01 11:24:57 +08:00
    Jrue0011
        1
    Jrue0011  
       Oct 31, 2023
    可以是可以...

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

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

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

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

    这是我目前的理解,我认为还是利大于弊的
    dadebucuo
        7
    dadebucuo  
       Oct 31, 2023
    不建议对 entity 进行继承操作, 可以定义公共字段的 get, set 方法作为接口, 子类来实现
    wolfie
        8
    wolfie  
       Oct 31, 2023 via Android
    bytebuddy 运行时重新定义。

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

    第一 MP 功能确实不够强大,其实对于 excludeProperty 本来应该是提供 @JsonIgnore 、 @JsonIgnoreParentProperties 这样单独的注解去实现的,同时还要留给外界一些扩展点类似 jackson 的 BeanSerializerModifier 去做自定义。
    第二虽然知道很多小项目怎么写都可以顺手就行,但是 DO 一把梭随便继承这种坏习惯能避免还是尽量避免,至于为啥不用继承这几乎是一种共识了,耦合度 继承 > 接口 > 组合。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   829 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 19:15 · PVG 03:15 · LAX 12:15 · JFK 15:15
    ♥ Do have faith in what you're doing.