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

时间:2022-02-02 11:58:38

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

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

 

通常我们使用自定义注解一般使用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.java
140 * @author xg.qiu
141 * @since JDK1.7
142 * Aug 3, 2015
143 * 自定义注解:列
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.java
174 * @author xg.qiu
175 * @since JDK1.7
176 * Aug 3, 2015
177 * 测试:使用自定义注解完成数据库的查询返回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、处理每个字段对应的sql
233 //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.拼装sql
254 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=1
select * 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')