zoukankan      html  css  js  c++  java
  • Java注解(Annotation)用法:利用注解和反射机制指定列名导出数据库数据

      闲来没事,想了一个应用的例子:用java如何把数据库的数据根据我们指定的某几列,如第2列,第4列,第6列导出来到Excel里

    写代码也是为了应用的,写好的代码更重要的是在于思考。我自己思考了这个示例。

    问题:指定列把数据库数据根据列导出到Excel里。

      那么要处理这个问题,它其实是很简单的,但是再简单的问题,也需要去拆分,思考,所谓,麻雀虽小,五脏俱全嘛。

    拆分:1. Load DB data; 2. 把数据和指定列映射起来;3. 导出数据到Excel。

      本文把第一步操作省略了,第一步操作就是读取数据库的数据,然后把它映射到Entity上去,也就是下面代买的Student.java,我们假设这一步已经成功。

    以下三个类重点实现第二步,第三步,只要把已经map好的数据,导出到Excel,可以利用apache poi,详见前一篇文章:java POI创建Excel示例(xslx和xsl区别 )

      第二步的实现我之前想着是直接把类的get方法用case的方式跟传进去的参数一一匹配,然后每次写数据的时候执行那个方法来获取当前要导出的列的数据。

    如下:

    1 public static Object getStudentInfo(Student student, int index) {
    2     switch(index) {
    3     case 1 :
    4         return student.getName();
    5     case 2 :
    6         return student.getSex();
    7     ...
    8     }
    9 }

    可是这样看起来太傻逼了,于是接着想有没有比较合理的方式实现呢?

    后来想到了用注解和java的反射机制来实现。

    现在java注解用途越来越广泛了,如Google的Guice,一轻量级的IOC框架,大有跟Spring抗衡的趋势。

    我就用注解来标注get方法获取的数据在数据库中对应列的索引,然后,根据传进去的列数组匹配get方法,再利用java的反射,执行方法体获取列的数据。具体代码如下。

    MapValue是一个Annotation,里面只有一个index()方法,用来标注方法的索引。

     1 package com.cnblogs.rolf.dao;
     2 
     3 
     4 import java.lang.annotation.ElementType;
     5 import java.lang.annotation.Retention;
     6 import java.lang.annotation.RetentionPolicy;
     7 import java.lang.annotation.Target;
     8 /**
     9  * 放在方法上的注解,这个注解可以映射方法的索引
    10  * @author 草原战狼
    11  *
    12  */
    13 @Target(value = {ElementType.METHOD})
    14 @Retention(RetentionPolicy.RUNTIME)
    15 public @interface MapValue {
    16     /**
    17      * 标注方法的索引
    18      * @return 方法索引值
    19      */
    20     int index() default 0;
    21 }
    View MapValue Code

    Student类是用来map到数据库的实体类,上面的get方法用MapValue标注了它在数据库中表列的顺序。

     1 package com.cnblogs.rolf.entity;
     2 
     3 import com.cnblogs.rolf.dao.MapValue;
     4 
     5 /**
     6  * Student 相当于一个表的实体类,我们可以假想它是从数据库读出来映射出来的一张表信息
     7  * STUDENT_COLUMN_NAMES: 这张表的类名
     8  * @author 草原战狼
     9  *
    10  */
    11 public class Student {
    12     public static String[] STUDENT_COLUMN_NAMES = {"Name", "Sex", "Age", "Height", "Weight", "Grade"};
    13     private String name;
    14     private String sex;
    15     private int age;
    16     private int height;
    17     private int weigth;
    18     private int grade;
    19     
    20     public Student(String name, String sex, int age, int height, int weight, int grade) {
    21         this.name = name;
    22         this.sex = sex;
    23         this.height = height;
    24         this.weigth = weight;
    25         this.age = age;
    26         this.grade = grade;
    27     }
    28     public Student() {
    29         
    30     }
    31     
    32     @MapValue(index = 1)
    33     public String getName() {
    34         return name;
    35     }
    36     public void setName(String name) {
    37         this.name = name;
    38     }
    39     @MapValue(index = 2)
    40     public String getSex() {
    41         return sex;
    42     }
    43     public void setSex(String sex) {
    44         this.sex = sex;
    45     }
    46     @MapValue(index = 3)
    47     public int getAge() {
    48         return age;
    49     }
    50     public void setAge(int age) {
    51         this.age = age;
    52     }
    53     @MapValue(index = 4)
    54     public int getHeight() {
    55         return height;
    56     }
    57     public void setHeight(int height) {
    58         this.height = height;
    59     }
    60     @MapValue(index = 5)
    61     public int getWeigth() {
    62         return weigth;
    63     }
    64     public void setWeigth(int weigth) {
    65         this.weigth = weigth;
    66     }
    67     @MapValue(index = 6)
    68     public int getGrade() {
    69         return grade;
    70     }
    71     public void setGrade(int grade) {
    72         this.grade = grade;
    73     }
    74 }
    View Student Code

    TestMain是测试的类,里面还有两个方法,这两个方法是用来处理实体类和要导出列数组的匹配。

     1 package com.cnblogs.rolf;
     2 
     3 import java.lang.reflect.InvocationTargetException;
     4 import java.lang.reflect.Method;
     5 
     6 import com.cnblogs.rolf.dao.MapValue;
     7 import com.cnblogs.rolf.entity.Student;
     8 /**
     9  * 可以应用在从数据库导出数据,根据指定要导出的列,导出到Excel, Word等。这个只是中间的环节
    10  * @author 草原战狼
    11  *
    12  */
    13 public class TestMain {
    14     public static void main(String[] args) {
    15         Student student = new Student("XiaoMing", "Male", 20, 175, 135, 2);
    16         int[] indexs = {34,2,5,3,0,1,2,4,6};
    17         System.out.println(student.getAge());
    18         String[] names = Student.STUDENT_COLUMN_NAMES;
    19         String printColumns = getColumnName(names, indexs);
    20         String pringStudentInfo = getStudentInfo(student, indexs);
    21         System.out.println(printColumns);
    22         System.out.println(pringStudentInfo);
    23     }
    24     /**
    25      * 接收一张表的实体类和外面传进来的要导出的列的索引顺序,比如要导出第2列,第4列,那么可以传入{2,4}
    26      * 返回获取到的指定列的值
    27      * @param student 表的实体类
    28      * @param indexs 要导出的列的索引
    29      * @return 指定列的值
    30      */
    31     public static String getStudentInfo(Student student, int[] indexs) {
    32         String studentInfo = "";
    33         Method[] methods = Student.class.getMethods();
    34         for(int index : indexs) {
    35             for(Method method : methods) {
    36                 MapValue mapValue = method.getAnnotation(MapValue.class);
    37                 if(mapValue == null){
    38                     continue;
    39                 }else {
    40                     if(index == mapValue.index()) {
    41                         Object value = null;
    42                         try {
    43                             value = method.invoke(student);
    44                         } catch (IllegalAccessException
    45                                 | IllegalArgumentException
    46                                 | InvocationTargetException e) {
    47                             System.out.println("parameters number is wrong.");
    48                             e.printStackTrace();
    49                         }
    50                         studentInfo += value.toString() + ", ";
    51                         break;
    52                     }
    53                 }
    54             }
    55         }
    56         return studentInfo;
    57     }
    58     /**
    59      * 根据指定的索引导出列的名称
    60      * @param names 整张表所有列的名称
    61      * @param indexs 要导出的列的索引
    62      * @return 导出的列的名称
    63      */
    64     public static String getColumnName(String[] names, int[] indexs) {
    65         String result = "";
    66         for(int index : indexs) {
    67             if(index > names.length || index < 1) {
    68                 continue;
    69             }
    70             result += names[index - 1] + ", ";
    71         }
    72         return result;
    73     }
    74 }
    View TestMain Code

    测试的结果:

    Sex, Weight, Age, Name, Sex, Height, Grade, 
    Male, 135, 20, XiaoMing, Male, 175, 2, 

    草原战狼淘宝小店:http://xarxf.taobao.com/ 淘宝搜小矮人鞋坊,主营精致美丽时尚女鞋,为您的白雪公主挑一双哦。谢谢各位博友的支持。

    ====================================================================================

    ======================    以上分析仅代表个人观点,欢迎指正与交流   =========================

    ======================    草原战狼博客,转载请注明出处,万分感谢   =========================

    ====================================================================================

  • 相关阅读:
    SQL Server Alwayson架构下 服务器 各虚拟IP漂移监控告警的功能实现 -2(虚拟IP视角)
    Android LitePal
    Android SQLite
    汇编语言知识点总结
    三层架构
    将博客搬至CSDN
    回溯(二)
    Android持久化技术
    Android广播时间——实现强制下线功能
    Android广播机制(2)
  • 原文地址:https://www.cnblogs.com/caoyuanzhanlang/p/3600930.html
Copyright © 2011-2022 走看看