欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java反射与注解结合使用(根据传入对象输出查询sql)

程序员文章站 2022-04-03 11:37:32
我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《java注解》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。 今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。 注解使用@interface 来定义,辣么我 ......

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

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

  注解使用@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();
        }
    }
}