你的位置:首页 > Java教程

[Java教程]使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句


这次给大家介绍一下在Java开发过程中 使用自定义注解开发:
主要知识点:
            1.反射            主要用于提取注解信息
            2.自定义异常  主要是为了自己自定义一个异常信息
            3.自定义注解  本次重点 学会如何自定义注解以及如何使用反射提取注解信息运用到实际开发
下图表示在Java中注解的含义以及注解的分类和如何解析注解

 

通常我们使用自定义注解一般使用4中元注解即:
@Target
@Retention
@Documented
@Inherited

 

 1 ** 2 *  3 */ 4 /** 5  * ClassName:package-info.java 6  * @author xg.qiu 7  * @since JDK1.7 8  * Aug 3, 2015 9  * 使用自定义注解: 10  * @Target :用于描述注解的使用范围(即:被描述的注解可以用在什么地方) 11  * 取值(ElementType)有: 12       1.ElementType.CONSTRUCTOR:用于描述构造器 13       2.ElementType.FIELD:用于描述域 14       3.ElementType.LOCAL_VARIABLE:用于描述局部变量 15       4.ElementType.METHOD:用于描述方法 16       5.ElementType.PACKAGE:用于描述包 17       6.ElementType.PARAMETER:用于描述参数 18       7.ElementType.TYPE:用于描述类、接口(包括注解类型) 或enum声明 19  @Retention :@Retention定义了该Annotation被保留的时间长短 20  取值(RetentionPoicy)有: 21     1.RetentionPolicy.SOURCE:在源文件中有效(即源文件保留) 22     2.RetentionPolicy.CLASS:在class文件中有效(即class保留) 23     3.RetentionPolicy.RUNTIME:在运行时有效(即运行时保留) 24  @Documented:用于描述其它类型的annotation应该被作为被标注的程序成员的公共API, 25          因此可以被例如javadoc此类的工具文档化。 26          Documented是一个标识注解,没有成员。 27  @Inherited :元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的 28          [必须是extend class 而不是implements interface] 29 */ 30 package com.demo.ann; 31  32 注解语法: 33 public @interface 注解名{ 34   35     // 注解变量 36    // 元数据类型:基本数据类型 String class enum Annotation 以及上述类型数组 37    // 如果元数据只有一个时 必须声明为value(); 38 } 39  40 /** 41  *  42 */ 43 package com.demo.ann.anns; 44  45 import java.lang.annotation.ElementType; 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.lang.annotation.Target; 49  50 /** 51  * ClassName:Table.java 52  * @author xg.qiu 53  * @since JDK1.7 54  * Aug 3, 2015 55  * 自定义注解:表 56  * 用法: 57  * @Table("user") 58  *   public class User 59 */ 60  61 @Target( ElementType.TYPE)// 作用域 类或接口 62 @Retention( RetentionPolicy.RUNTIME)// 有效期为运行时 63 public @interface Table { 64   String value(); 65 } 66  67  68  69 /** 70  *  71 */ 72 package com.demo.ann; 73  74 import com.demo.ann.anns.Column; 75 import com.demo.ann.anns.Table; 76  77 /** 78  * ClassName:User.java 79  * JAVABean 用户实体类 80  * @author xg.qiu 81  * @since JDK1.7 Aug 3, 2015 82 */ 83 @Table("TABLE_USER") 84 public class User { 85   @Column("USER_ID") 86   private int userId; 87   @Column("USER_NAME") 88   private String userName; 89   @Column("PASS_WORD") 90   private String passWord; 91   @Column("AGE") 92   private int age; 93  94   public int getUserId() { 95     return userId; 96   } 97  98   public void setUserId(int userId) { 99     this.userId = userId;100   }101 102   public String getUserName() {103     return userName;104   }105 106   public void setUserName(String userName) {107     this.userName = userName;108   }109 110   public String getPassWord() {111     return passWord;112   }113 114   public void setPassWord(String passWord) {115     this.passWord = passWord;116   }117 118   public int getAge() {119     return age;120   }121 122   public void setAge(int age) {123     this.age = age;124   }125 }126 127 128 /**129  * 130 */131 package com.demo.ann.anns;132 133 import java.lang.annotation.ElementType;134 import java.lang.annotation.Retention;135 import java.lang.annotation.RetentionPolicy;136 import java.lang.annotation.Target;137 138 /**139  * ClassName:Column.java140  * @author xg.qiu141  * @since JDK1.7142  * Aug 3, 2015143  * 自定义注解:列144  * 用法:145  *     @Column("userId")146  *     private int userId;147 */148 @Target( ElementType.FIELD)//作用于属性149 @Retention( RetentionPolicy.RUNTIME)//有效期为运行时150 public @interface Column {151   String value();152 }153 154 155 156 157 158 /**159 160  * 161 */162 package com.demo.ann;163 164 import java.lang.reflect.Field;165 import java.lang.reflect.Method;166 167 import com.demo.ann.anns.Column;168 import com.demo.ann.anns.Table;169 import com.demo.ann.exception.AnnException;170 171 /**172   解析注解并返回执行的sql语句 173  * ClassName:Test.java174  * @author xg.qiu175  * @since JDK1.7176  * Aug 3, 2015177  * 测试:使用自定义注解完成数据库的查询返回sql语句178  *     1.根据id查询179  *     2.根据用户名查询180  *     3.根据用户名、密码组合查询181 */182 public class Test {183   public static void main(String[] args) {184     User user1 = new User();185     user1.setUserId(1);//根据Id查询186     187     User user2 = new User();188     user2.setUserName("xiaoqiu");// 根据用户名查询189     190     User user3 = new User();191     user3.setUserName("xiaoqiu");192     user3.setPassWord("123456");// 根据用户名、密码组合查询193     194     User user4 = new User();195     user4.setUserName("xiaoqiu,zasang,lisi");196     197     String sql1 = executeQuery(user1);198     String sql2 = executeQuery(user2);199     String sql3 = executeQuery(user3);200     String sql4 = executeQuery(user4);201     202     System.out.println(sql1);203     System.out.println(sql2);204     System.out.println(sql3);205     System.out.println(sql4);206     207   }208     /**209      * @param user 用户对象210      *@return String 返回的是拼装好的sql语句211      */212   private static String executeQuery(User user) {213     StringBuffer sb = new StringBuffer("select * from ");214     //1、获取类215     Class<? extends User> c = user.getClass();216     //2、查找类是否被注解217     boolean isExist = c.isAnnotationPresent(Table.class);218     if(!isExist){219       try {220                 // 自定义异常221         throw new AnnException("the "+ c.getClass().getName() +" class is not used annotation");222       } catch (AnnException e) {223         e.printStackTrace();224       }225     }226         // 获取Table注解 227     Table table = (Table) c.getAnnotation(Table.class);228     sb.append( table.value() +" where 1= 1");229     //3、查找属性是否被注解230     Field[] fields = c.getDeclaredFields();231     for(Field f : fields){232       //3.1、处理每个字段对应的sql233       //3.2、拿到字段值234       boolean isFExist = f.isAnnotationPresent(Column.class);235       if(!isFExist){236         try {237           throw new AnnException("the " + f.getName() +" field is not used annotation");238         } catch (AnnException e) {239           e.printStackTrace();240         }241       }242             // 获取列注解 243       Column column = f.getAnnotation(Column.class);244       String columnName = column.value();245       //3.2、获取字段246       String fieldName = f.getName();247       //3.4、.拿到字段值248       Object values = null;249       String getFieldMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);250       try {251         Method getMethod = c.getDeclaredMethod(getFieldMethodName);252         values = getMethod.invoke(user);253         //3.5.拼装sql254         if( values == null || ( values instanceof Integer && (Integer) values == 0) ){255           continue;256         }257         sb.append(" and ").append(columnName);258         if(values instanceof Integer){259           sb.append("=").append(values);260         }else if(values instanceof String){261           if( ((String) values).contains(",")){262             String [] valuesIn = ((String) values).split(",");263             sb.append(" in('");264             for(String s : valuesIn){265               sb.append(s).append("'").append(",");266             }267             sb.deleteCharAt(sb.length() - 1);268             sb.append(")");269           }else{270             sb.append("='").append(values).append("'");271           }272         }273       } catch (Exception e) {274                 // 打印堆栈信息 275         e.printStackTrace();276       }277     }278         // 返回拼装好的sql语句 279     return sb.toString();280   }281 }

运行效果:
 
select * from TABLE_USER where 1= 1 and USER_ID=1select * from TABLE_USER where 1= 1 and USER_NAME='xiaoqiu'select * from TABLE_USER where 1= 1 and USER_NAME='xiaoqiu' and PASS_WORD='123456'select * from TABLE_USER where 1= 1 and USER_NAME in('xiaoqiu',zasang',lisi')