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 }
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 }
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 }
测试的结果:
Sex, Weight, Age, Name, Sex, Height, Grade,
Male, 135, 20, XiaoMing, Male, 175, 2,
草原战狼淘宝小店:http://xarxf.taobao.com/ 淘宝搜小矮人鞋坊,主营精致美丽时尚女鞋,为您的白雪公主挑一双哦。谢谢各位博友的支持。
====================================================================================
====================== 以上分析仅代表个人观点,欢迎指正与交流 =========================
====================== 草原战狼博客,转载请注明出处,万分感谢 =========================
====================================================================================