java反射与注解结合使用(根据传入对象输出查询sql)
博客已迁移到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)的更多相关文章
- Java反射,注解,以及动态代理
Java反射,注解,以及动态代理 基础 最近在准备实习面试,被学长问到了Java反射,注解和动态代理的内容,发现有点自己有点懵,这几天查了很多资料,就来说下自己的理解吧[如有错误,望指正] Java ...
- 利用反射跟自定义注解拼接实体对象的查询SQL
前言 项目中虽然有ORM映射框架来帮我们拼写SQL,简化开发过程,降低开发难度.但难免会出现需要自己拼写SQL的情况,这里分享一个利用反射跟自定义注解拼接实体对象的查询SQL的方法. 代码 自定义注解 ...
- JavaSE学习总结(十五)—— Java反射与注解
一.静态语言与动态语言 静态类型语言:是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.强类型 动态 ...
- Java反射及注解
一.反射 1.动态语言:是指程序在运行是可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见的JavaScript就是动态语言,除此以外Python等也属于动态语言,而C.C ...
- java 反射,注解,泛型,内省(高级知识点)
Java反射 1.Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs 取得任何一个已知名称的class的内部信息, 包括 ...
- java反射获取注解并拼接sql语句
先建两个注解 分别为 Table 和 Column package com.hk.test; import java.lang.annotation.ElementType; import java. ...
- 【转】JAVA反射与注解
转载自:https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/ 前言 现在在我们构建自己或公司的项目中,或多或少都会依赖几 ...
- JAVA反射机制_获取字节码文件对象
是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为java语 ...
- Java 反射、注解
1. 泛型 基本用法.泛型擦除.泛型类/泛型方法/泛型接口.泛型关键字.反射泛型! a. 概述 泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型转化! // 运行时期异常 ...
随机推荐
- 简单工厂模式-Java篇
简单工厂模式就是考虑如何实例化对象的问题,就是说到底要实例化谁,将来会不会增加实例化对象,比如计算器类中增加开根元素,应该考虑用一个单独的类来创造实例的过程,这就是工厂.下面将利用计算器类举例,解释简 ...
- Android 使用EventBus进行Fragment和Activity通信
本文介绍EventBus的基本使用,以及用于Fragment和Activity之间通信. github地址: https://github.com/greenrobot/EventBus 版本是 Ev ...
- Android基础夯实--重温动画(四)之属性动画 ValueAnimator详解
宝剑锋从磨砺出,梅花香自苦寒来:千淘万漉虽辛苦,吹尽狂沙始到金: 长风破浪会有时,直挂云帆济沧海 一.摘要 Animator类作为属性动画的基类,它是一个抽象类,它提供了实现动画的基本架构,但是我们不 ...
- Windows下使用JMeter
简介 Apache JMeter是100%纯java桌面应用程序,被设计用来测试C/S结构的软件(例如web应用程序).它可以被用来测试包括基于静态和动态资源程序的性能,例如静态文件,Java Ser ...
- [转]JavaScript线程运行机制
从开始接触js时,我们便知道js是单线程的.单线程,异步,同步,互调,阻塞等.在实际写js的时候,我们都会用到ajax,不管是原生的实现,还是借助jQuery等工具库实现,我们都知道,ajax可以实现 ...
- iTOP-4418开发板最新资料及例程
开发板资料: 开发板硬件资源: 1.POWER电源接口 电源输入为 5V/2A+,给核心板 AXP228 电源管理芯片提供 5V 电源. 2.SWITCH电源开关 轻触电源开关可以控制开发板电源通断. ...
- WPF学习- 新建项目后自定义Main()[Type 'App' already defines a member called 'Main' with the same parameter types]
问题点: 在App.xaml.cs中自己添加Main方法,编译会出现如下报错: 错误 CS0111 类型“App”已定义了一个名为“Main”的具有相同参数类型的成员 错误 Type 'App' a ...
- caffe实现自己的层
http://blog.csdn.net/xizero00/article/details/52529341 将这篇博客所讲进行了实现 1.LayerParameter也在caffe.proto文件中 ...
- PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (三) -- Header Exchange
此模式下,消息的routing key 和队列的 routing key 会被完全忽略,而是在交换机推送消息和队列绑定交换机时, 分别为消息和队列设置 headers 属性, 通过匹配消息和队列的 h ...
- Bzoj 3307 雨天的尾巴(线段树合并+树上差分)
C. 雨天的尾巴 题目描述 N个点,形成一个树状结构.有M次发放,每次选择两个点x,y对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成所有发放后,每个点存放最多的是哪种物品. 输入格式 第 ...