如何修改注解里面的属性值

news2024/11/15 8:21:32

说明:Java中,注解里的属性值在编译时就已经固定了,是无法通过AOP或者反射技术直接去修改的。本文介绍如何通过动态代理的方式来修改属性值。

搭建环境

首先,创建一个简单的Spring Boot项目,pom.xml文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/>
    </parent>

    <groupId>com.hezy</groupId>
    <artifactId>tk_mapper_demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>Archetype - tk_mapper_demo</name>
    <url>http://maven.apache.org</url>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>4.1.5</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.8</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

场景描述

如下,是一个实体类,属性limit因为和MySQL的关键字冲突,所以用@Column注解做了转义

import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;

@Table(name = "i_users")
@Data
public class User implements Serializable {

    @Id
    private Integer id;

    private String username;

    private String password;
    
    @Column(name = "`limit`")
    private String limit;
}

数据访问层如下,继承框架自带的Mapper,可以使用它的一些API

import com.hezy.pojo.User;
import org.springframework.stereotype.Repository;
import tk.mybatis.mapper.common.Mapper;

@Repository
public interface UserRepository extends Mapper<User> {
}

接口访问数据库,直接使用其对应的API,如下:

    @GetMapping("/hello/{id}")
    public User hello(@PathVariable Long id) {
        return userRepository.selectByPrimaryKey(id);
    }

能成功访问,没得问题

在这里插入图片描述

现在问题来了,这个实体类是与数据库技术深度绑定的。实体类User的limit属性名的转义方式是MySQL的,如果数据库换成了postgres,而postgres对关键字的转义使用双引号的,这样就会报错。如下:

(去掉mysql,换成postgresql)

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.7.3</version>
        </dependency>

<!--        <dependency>-->
<!--            <groupId>com.mysql</groupId>-->
<!--            <artifactId>mysql-connector-j</artifactId>-->
<!--            <scope>runtime</scope>-->
<!--        </dependency>-->

访问接口,报语法错误

在这里插入图片描述

当然,会有同学问,一个项目不可能用两种数据库,但是如果你们公司是做SaaS应用的,要面对不同行业的客户,需要同时支持MySQL、Postgres,要在这两种数据库之间切换使用,那么这个问题是很棘手的。

博主自己想了几种办法,如下,

在这里插入图片描述

可行方法,是技术上可行,但不一定是好的。因为要考虑代码侵入、发布上线等一些场外因素。

动态代理

场景介绍完了,理一下。两种数据库对关键字的转义不同,且无法兼容,会直接报错。而转义字符是直接写在实体类属性上的,通过@Column注解,最后注解里面的name值是在编译时就固定了的,运行是无法改动,也就是说通过AOP去根据数据库类型(DBType)拼接不同的转义符是行不通的,无法改,改了也没法生效。

一筹莫展之际,我牛逼的同事给了我一个工具类,里面可以通过动态代理的方式,获取到JDK底层对象memberValues并修改。可以改就好办了,可以在项目启动时,主动走这个逻辑,把项目中相关实体类字段都改掉。

    @PostConstruct
    public void init() throws NoSuchFieldException, IllegalAccessException {
        // 动态代理,获取实体类指定属性的上的注解
        InvocationHandler invocationHandler = Proxy.getInvocationHandler(User.class
                .getDeclaredField("limit")
                .getAnnotation(Column.class));
        // 反射获取memberValues
        Field f = invocationHandler.getClass().getDeclaredField("memberValues");
        f.setAccessible(true);
        Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
        // 修改注解的name值,把MySQL的转义方式换成postgresql的
        memberValues.put("name", "\"limit\"");
    }

改完之后,重新访问,如下,可以看到能正常访问数据库了

在这里插入图片描述

总结

本文介绍了一种修改注解里面属性值的方式,非常有启发,感觉自己功力大增。但这种方式,AI不推荐在生产环境中使用,理由有下:

  • 涉及JDK内部实现,可能会破坏代码的可维护性和稳定性;

  • 如上,关联到JDK内部实现细节,会有可移植性问题;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2078296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

声音事件检测DESED 数据集介绍

DESED dataset contains:DESED Domestic Environment sound event detection; 家庭环境声音事件检测&#xff1b; 1. 数据 Content内容 DESED dataset contains:DESED 数据集包含&#xff1a; Domestic Environment sound event detection; 家庭环境声音事件检测&#xff1…

[学习笔记]在不同项目中切换Node.js版本

文章目录 使用 Node Version Manager (NVM)安装 NVM使用 NVM 安装和切换 Node.js 版本为项目指定 Node.js 版本 使用环境变量指定 Node.js安装多个版本的 Node.js设置环境变量验证配置使用 npm 脚本切换 在开发中&#xff0c;可能会遇到不同的Vue项目需要不同的Node.js&#xf…

各个版本jdk新特性

jdk8新特性 方法引用&#xff1a;方法引用允许直接通过方法的名称来引用已经存在的方法&#xff0c;简化了函数式接口的实现。默认方法&#xff08;Default Methods&#xff09;&#xff1a;默认方法允许在接口中定义具有默认实现的方法&#xff0c;以便接口的实现类可以继承该…

uniapp-Vue项目如何实现国际化,实现多语言切换,拒绝多套开发,一步到位,看这篇就够

一 安装 找到自己的项目,输入cmd进入命令行,输入安装命令,点击回车进行下载: npm install vue-i18nnext 下载完将在项目的配置文件中看到: 二 使用 2.1 在项目中创建一个文件夹如:lang 用于存放不同语言的包。这些语言文件通常为JSON格式 2.2 在项目main.js文件中引入并初…

YoloV8损失函数篇(代码加理论)

首先yolov8中loss的权重可以在ultralytics/cfg/default.yaml修改 损失函数定义ultralytics/utils/loss.py 回归分支的损失函数 DFL(Distribution Focal Loss)&#xff0c;计算anchor point的中心点到左上角和右下角的偏移量IoU Loss&#xff0c;定位损失&#xff0c;采用CIoU…

开源网络安全大模型 - SecGPT

网络安全大模型是指使用大量数据和参数来训练的人工智能模型&#xff0c;它可以理解和生成与网络安全相关的内容&#xff0c;例如漏洞报告、利用代码、攻击场景等。 目前各家网络安全厂商也纷纷跟进在大模型方面的探索&#xff0c;但可供广大从业者研究的特有网络安全大模型…

2013-2023年 中国MOD17A3H植被净初级生产力(NPP)数据

中国MOD17A3H植被净初级生产力&#xff08;NPP&#xff09;数据是基于NASA的MODIS卫星遥感数据计算得出的&#xff0c;这些数据对于评估生态系统碳收支、碳循环以及气候变化的影响具有重要意义。NPP数据可以反映植被通过光合作用固定大气中二氧化碳并转化为有机物质的能力&…

OpenStack组件介绍(2)

cinder 提供块存储服务&#xff0c;管理openstack中的块存储资源&#xff0c;为云平台提供持久的块存储服务&#xff0c;通过驱动的方式可以接入不同种类的后端存储。 cinder对接nfs 关闭防火墙和selinux [rootlocalhost yum.repos.d]# systemctl stop firewalld [rootlocal…

对想学习人工智能或者大模型技术从业者的建议

“ 技术的价值在于应用&#xff0c;理论与实践相结合才能事半功倍” 写这个关于AI技术的公众号也有差不多五个月的时间了&#xff0c;最近一段时间基本上都在保持日更状态&#xff0c;而且写的大部分都是关于大模型技术理论和技术方面的东西。‍‍‍‍‍‍‍‍‍ 然后最近一段…

网络安全售前入门04——审计类产品了解

目录 1.前言 2.数据库审计介绍 2.1产品架构功能 2.2应用场景 2.3部署形式 2.4产品价值 2.5选型依据 1.前言 为方便初接触网络安全售前工作的小伙伴了解网安行业情况,我制作一系统售前入门(安全产品,安全服务,法律法规等)文章介绍,希望能给初进网安职场的小伙伴提供…

STL中的stack与queue

前言&#xff1a; stack与queue是STL中的容器适配器&#xff0c;而不是容器。何为适配器&#xff1f;给手机充电的充电器就是一种适配器&#xff0c;将高电压变成低电压。适配器是用来做转化的&#xff0c;不用来直接管理数据&#xff0c;而是在其他容器的基础上去封装转换。 …

WordNet介绍——一个英语词汇数据库

传统语义知识库最常见的更新方法是依赖人工手动更新&#xff0c;使用这种更新方法的语义知识库包括最早的 WordNet、FrameNet和 ILD&#xff0c;以及包含丰富内容的 ConceptNet和 DBPedia。此类语义知识库的特点是以单词作为语义知识库的基本构成元素&#xff0c;以及使用预先设…

C++ | Leetcode C++题解之第376题摆动序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();if (n < 2) {return n;}int prevdiff nums[1] - nums[0];int ret prevdiff ! 0 ? 2 : 1;for (int i 2; i < n; i) {int diff n…

记一次NULL与空字符串导致的分组后产生重复数据

目录 一&#xff0c;场景说明二&#xff0c;实现功能三&#xff0c;修改原实现方法四&#xff0c;说明 一&#xff0c;场景说明 想实现这样一个功能&#xff0c;统计人员信息中不同性别的人的总工资。 实现方式&#xff1a;将数据group by 分组后累加。 二&#xff0c;实现功…

叉车(工业车辆)安全管理系统,云端监管人车信息运营情况方案

近年来&#xff0c;国家和各地政府相继出台了多项政策法规&#xff0c;从政策层面推行叉车智慧监管&#xff0c;加大叉车安全监管力度。同时鼓励各地结合实际&#xff0c;积极探索智慧叉车建设&#xff0c;实现作业人员资格认证、车辆状态认证、安全操作提醒、行驶轨迹监控等&a…

探秘Facebook的人工智能战略:如何用智能技术重塑社交网络

人工智能&#xff08;AI&#xff09;正以前所未有的速度渗透到各个领域&#xff0c;社交网络也不例外。作为全球最大的社交平台之一&#xff0c;Facebook&#xff08;现Meta&#xff09;正利用人工智能技术重塑其网络环境&#xff0c;提升用户体验。本文将深入探讨Facebook的人…

对SpringBoot项目Jar包进行加密防止反编译

最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去,要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来,本文介绍了如何对SpringBoot项目Jar包进行加密防止反编译,需要的朋友可以参考下 场景: 最近项目要求部署到其他公司的服…

华为HCIP-datacom 真题 (2024年下半年最新题库)

备考HCIP-datacom的小伙伴注意啦 2024年下半年8月份最新题库带解析,有需要的小伙伴移动至文章末 1.BGP 邻居建立过程的状态存在以下几种&#xff1a;那么建立一个成功的连接所经历的状态机顺序是 A、3-1-2-5-4 B、1-3-5-2-4 C、3-5-1-2-4 D、3-1-5-2-4 答案&#xff1a;D 解析…

界面控件DevExpress VCL v24.2路线图预览——增强云集成、简化应用程序皮肤等

DevExpress VCL Controls是Devexpress公司旗下老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下一…

el-pagination 下拉条目数最后一个样式改成全部

2024.08.27今天我学习了如何把el-pagination的下拉条目数修改&#xff0c;效果如下&#xff1a; 我们需要把最后一条选择换成全部展示&#xff0c;其实传给后端的还是总的数量&#xff0c;只是换了一个content&#xff0c; 通过f12查看元素可以拿到.el-select-dropdown__item …