Java应用开发各种奇葩的问题

Java应用开发各种奇葩BUG

  • 1、Lombok
    • 1.1 创建子类,无法对父类属性进行赋值
  • 2、MybatisPLus
    • 2.1 MybatisPLus自动填充公共参数
  • 3、参考

1、Lombok

1.1 创建子类,无法对父类属性进行赋值

  1. @Data 和@Builder 不可以混用
    @Builder 和 @Data 搭配使用,导致生成的构造器是可变的,它允许使用 setter 方法修改构造器的状态。这违反了构造器模式的原则,构造器应该是不可变的,一旦创建就不能被修改。
    **注意:**如果非要使用 @Builder ,那么不要用 @Data ,要用 @Getter。相对来说,反而 @Accessors 的行为更符合这个要求。
  2. @Data 无法对父类属性进行赋值
  • @Data注解可以用来生成类的getter、setter、构造方法和toString方法。然而,默认情况下,它只会考虑当前类中存在的属性(字段),而不会考虑其父类中的属性。如果你希望@Data也考虑父类中的属性,需要使用@Accessors注解和@Data一起使用。
@Accessors(fluent=true)
public class Parent {
    private int parentProperty;
}

@Data
public class Child extends Parent {
    private int childProperty;
}

Child child = new Child();
child.setParentProperty(10);
child.setChildProperty(20);
System.out.println(child); // prints Child{parentProperty=10, childProperty=20}

  • 如果父类用了@Data 此时子类如何给父类属性赋值
    如果父类使用了@Data注解,子类可以通过以下两种方式给父类复制属性: 使用@Accessors(fluent=true)注解:在子类上添加@Accessors(fluent=true)注解,可以使得子类的属性可以通过链式调用的方式进行赋值,这样就可以使用子类给父类复制属性。例如:
@Data
public class Parent {
    private String name;
}

@Data
@Accessors(fluent=true)
public class Child extends Parent {
    private String age;
}

Child child = new Child();
child.setName("John").setAge("18");
Parent parent = child.toParent();

  • 使用@AccessorsPrefix注解:在子类上添加@AccessorsPrefix注解,可以为子类的属性指定前缀,以区分子类和父类的属性。例如:
@Data
public class Parent {
    private String name;
}

@Data
@Accessors(prefix = "p")
public class Child extends Parent {
    private String age;
}

Child child = new Child();
child.setName("John").setAge("18");
Parent parent = child.toParent();

  1. @AllArgsConstructor 构造函数 无法初始化父类的属性
    @AllArgsConstructor注解只能用来生成具有指定参数的构造函数,它并不会初始化父类的属性。 如果希望初始化父类的属性,可以在子类的@AllArgsConstructor注解的父类属性上添加@ToString(callSuper = true);
    @EqualsAndHashCode(callSuper = true)
  2. @ToString(callSuper =true) 实现toString 属性覆盖父类
  3. @EqualsAndHashCode(callSuper = true)覆盖父类

2、MybatisPLus

2.1 MybatisPLus自动填充公共参数

在MyBatis Plus中,可以使用@FillInsert和@FillUpdate注解来自动填充公共参数。 @FillInsert:用于填充insert操作的公共参数,默认情况下,会将注解所在的字段自动添加到插入语句中。 @FillUpdate:用于填充update操作的公共参数,默认情况下,会将注解所在的字段自动添加到更新语句中。 示例代码如下:

public class BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 搜索值
     */
    @JsonIgnore
    @TableField(exist = false)
    private String searchValue;

    /**
     * 创建者
     */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;

    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /**
     * 更新者
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;

    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    /**
     * 请求参数
     */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @TableField(exist = false)
    private Map<String, Object> params = new HashMap<>();

}
  • 添加配置
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;

import java.util.Date;

/**
 * MP注入处理器
 *
 * @Author: water
 * @Date: 2023/11/15 8:51
 * @Version: 1.0.0
 */
@Slf4j
public class CreateAndUpdateMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        try {
            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
                Date createTime = ObjectUtil.isNotNull(baseEntity.getCreateTime())
                        ? baseEntity.getCreateTime() : new Date();
                Date updateTime = ObjectUtil.isNotNull(baseEntity.getUpdateTime())
                        ? baseEntity.getUpdateTime() : new Date();
                // 解析了有数据填充的问题
                baseEntity.setCreateTime(createTime);
                baseEntity.setUpdateTime(updateTime);
                String username = StringUtils.isNotBlank(baseEntity.getCreateBy())
                        ? baseEntity.getCreateBy() : getLoginUsername();
                // 当前已登录 且 创建人为空 则填充
                baseEntity.setCreateBy(username);
                // 当前已登录 且 更新人为空 则填充
                baseEntity.setUpdateBy(username);
            }
        } catch (Exception e) {
            throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        try {
            if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
                Date current = new Date();
                // 更新时间填充(不管为不为空)
                baseEntity.setUpdateTime(current);
                String username = getLoginUsername();
                // 当前已登录 更新人填充(不管为不为空)
                if (StringUtils.isNotBlank(username)) {
                    baseEntity.setUpdateBy(username);
                }
            }
        } catch (Exception e) {
            throw new ServiceException("自动注入异常 => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED);
        }
    }

    /**
     * 获取登录用户名
     */
    private String getLoginUsername() {
        LoginUser loginUser;
        try {
            loginUser = LoginHelper.getLoginUser();
        } catch (Exception e) {
            log.warn("自动注入警告 => 用户未登录");
            return null;
        }
        return ObjectUtil.isNotNull(loginUser) ? loginUser.getUsername() : null;
    }

}

3、参考

你可能感兴趣的:(Java体系,java,python,开发语言)