博客已迁移到CSDN《https://blog.csdn.net/qq_33375499

  我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《java注解》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。

  今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。

  注解使用@interface 来定义,辣么我们自定义的注解,该使用获取到并且指明该注解的作用呢?java提供了反射机制,通过类的类类型我们可以根据自己需要老操作该类。有管反射的知识,可以参考我的上两章博客。好了,废话不多说,我们上代码:

 需求:创建一个与数据库表对应的实体类,通过使用注解的方式,来生成该实体类的查询sql语句。

  1.创建Table类注解,用于标明该类对应数据库的表名称

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}

  2.创建Column字段注解,用于标明该类中属性与数据库表字段的映射

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}

  3.创建实体类,并使用注解Table、Column

/**
* 数据库 user表,对应表字段为 userid/username/age/addredd
*/
@Table("user")
public class User {
@Column("userid")
private String userid;
@Column("username")
private String username;
@Column("age")
private int age;
@Column("sl")
private double sl;
@Column("address")
private String address;
// 添加一个不是数据库的字段: 用于测试
private String noField; public double getSl() {
return sl;
} public void setSl(double sl) {
this.sl = sl;
} public String getNoField() {
return noField;
} public void setNoField(String noField) {
this.noField = noField;
} public String getUserid() {
return userid;
} public void setUserid(String userid) {
this.userid = userid;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getAddress() {
return address;
} public void setAddress(String address) {
this.address = address;
}
}

  4.创建工具类,根据传入该对象,来生成对应的查询sql

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects; /**
* 注解
*/
public class AnnotationUtil {
/**
* 根据传入的对象 来生成query sql
*
* @param object
* @return
*/
public static String getSqlByAnnotation(Object object) throws Exception {
// 使用StringBuilder 线程安全
StringBuilder sb = new StringBuilder();
// 检查参数是否为空
Objects.requireNonNull(object, "该对象不能为空!");
// 1.通过反射获取该对象的类类型
Class c = object.getClass();
// 2.获取该对象的 类注解: 标明表名
boolean table_flag = c.isAnnotationPresent(Table.class);
if (!table_flag) {
throw new NullPointerException();
}
Table table = (Table) c.getDeclaredAnnotation(Table.class);
sb.append("SELECT * FROM ").append(table.value()).append(" WHERE 1 = 1");
// 3.获取该对象的 字段注解:显示查询字段
Field[] fields = c.getDeclaredFields();
boolean field_flag;
Column column;
String field_name;
Method menthod;
Object val;
for (Field field : fields) {
// 首先得拿到字段名称:通过字段上的注解标明该指定是数据库表对应的字段
field_flag = field.isAnnotationPresent(Column.class);
if (!field_flag) {
continue;
}
column = field.getDeclaredAnnotation(Column.class);
// 其次得拿到字段值 : 通过反射调用类的getXxxx方法
field_name = field.getName();
menthod = c.getDeclaredMethod("get" + Character.toUpperCase(field_name.charAt(0)) + field_name.substring(1));
val = menthod.invoke(object);
// 判断该字段是否为空,不为空,才进行append
// 这里要注意:有些属性不赋值时候,java会自动生成默认值,如Double默认为0.0
// 还有其他类型,小伙伴们可以自行测试
if (!Objects.isNull(val)) {
if((val instanceof Double) && (double) val == 0.0){
continue;
}
sb.append(" AND ").append(column.value()).append(" = ");
sb.append(val);
}
}
return sb.toString();
} public static void main(String[] args) {
User user = new User();
user.setUserid("0001");
user.setAge(23);
// 用于测试没有带Column注解的字段
user.setNoField("field");
try {
System.out.println(AnnotationUtil.getSqlByAnnotation(user));
} catch (Exception e) {
e.printStackTrace();
}
}
}

java反射与注解结合使用(根据传入对象输出查询sql)的更多相关文章

  1. Java反射,注解,以及动态代理

    Java反射,注解,以及动态代理 基础  最近在准备实习面试,被学长问到了Java反射,注解和动态代理的内容,发现有点自己有点懵,这几天查了很多资料,就来说下自己的理解吧[如有错误,望指正] Java ...

  2. 利用反射跟自定义注解拼接实体对象的查询SQL

    前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...

  3. JavaSE学习总结(十五)—— Java反射与注解

    一.静态语言与动态语言 静态类型语言:是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.强类型 动态 ...

  4. Java反射及注解

    一.反射 1.动态语言:是指程序在运行是可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见的JavaScript就是动态语言,除此以外Python等也属于动态语言,而C.C ...

  5. java 反射,注解,泛型,内省(高级知识点)

     Java反射 1.Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs    取得任何一个已知名称的class的内部信息, 包括 ...

  6. java反射获取注解并拼接sql语句

    先建两个注解 分别为 Table 和 Column package com.hk.test; import java.lang.annotation.ElementType; import java. ...

  7. 【转】JAVA反射与注解

    转载自:https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/ 前言 现在在我们构建自己或公司的项目中,或多或少都会依赖几 ...

  8. JAVA反射机制_获取字节码文件对象

    是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为java语 ...

  9. Java 反射、注解

    1. 泛型 基本用法.泛型擦除.泛型类/泛型方法/泛型接口.泛型关键字.反射泛型! a. 概述 泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型转化! // 运行时期异常 ...

随机推荐

  1. 组合模式和php实现

    组合模式(有时候又叫做部分-整体模式): 将对象组合成树形结构以表示“部分整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.它使我们树型结构的问题中,模糊了简单元素和复杂元素的概 ...

  2. 移动端rem

    手机有很多尺寸的型号.使用rem来做为大小单位可以达到兼容的目的. 方法一:js测量手机尺寸,设置font-size:为手机屏幕width /10 + ‘px’.即10rem 为手机屏幕width. ...

  3. 微信小程序组件解读和分析:七、button按钮

    button按钮组件说明: button,顾名思义,按钮,类似于html的button标签.我们可以设置按钮的属性,比如字体颜色大小,背景颜色等,可以给按钮绑定事件,用户点击时会触发事件. butto ...

  4. SQL Server性能调优——报表数据库与业务数据库分离

    前段时间把公司的主数据库切了,分成业务库和报表库,业务库向报表库进行实时的Replication.这个项目的上线提升了系统的性能和可维护性,现在把设计时的考量和所做的工作重新回顾一下,作为备忘. 项目 ...

  5. ubuntu 下安装redis

    获取Redis 1.通过官网http://redis.io/获取稳定版源码包下载地址: 2.通过wget http://download.redis.io/releases/redis-3.0.2.t ...

  6. tab切换组件nz-tab

    <nz-card [nzBordered]="true" nzTitle="卡片标题"> <nz-card style="width ...

  7. docker 入门学习

    一 : docker 安装(linux-centos7) 安装docker要求 1.docker只支持在64位cup架构计算机上运行,目前不支持32位cup. 2.建议系统的linux内核版本在3.1 ...

  8. 【转】MFC 自定义edit 限制输入十六进制内容 响应复制粘贴全选剪切的功能

    参考地址:MFC 自定义edit 限制输入内容 响应复制粘贴全选剪切的功能   Ctrl组合键ASCII码 ^Z代表Ctrl+z                     ASCII值 控制字符  AS ...

  9. vue工程化:返回顶部和底部的动画效果

    . <template> <div> <div class="scroll" :class="{show:isActive}"&g ...

  10. OpenMP用法大全

    OpenMP基本概念OpenMP是一种用于共享内存并行系统的多线程程序设计方案,支持的编程语言包括C.C++和Fortran.OpenMP提供了对并行算法的高层抽象描述,特别适合在多核CPU机器上的并 ...