zoukankan      html  css  js  c++  java
  • 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();
            }
        }
    }
  • 相关阅读:
    Linux常用基本命令:三剑客命令之-awk数组用法
    Linux常用基本命令:三剑客命令之-awk动作用法(1)
    Linux常用基本命令:三剑客命令之-awk模式用法(2)
    Linux常用基本命令:三剑客命令之-awk模式用法(1)
    Linux常用基本命令:三剑客命令之-awk格式化动作
    Linux常用基本命令:三剑客命令之-awk内置变量与自定义变量
    Linux常用基本命令:三剑客命令之-awk输入输出分隔符
    Linux常用基本命令:三剑客命令之-awk基础用法
    Linux环境变量详解与应用
    在js中怎么判断两个字符串相等
  • 原文地址:https://www.cnblogs.com/www-123456/p/10887576.html
Copyright © 2011-2022 走看看