注解实践
粗略的做一个简单实践,做一个ORM小方案,通过注解来实现
- 一张user表信息,字段: id、用户名、昵称、年龄、性别、地址、邮箱、手机号
- 简单的对每个字段或组合条件进行检索,打印SQL方式来显示结果
对数据执行检索,就要考虑怎么和数据库进行映射,数据对应有表名,字段名,人为定义的user也最相似于数据库表,比如JPA或其他,在user对象上可以加@Table、@Entry、@Column等注解标识,以对应数据库的表信息
下面创建注解@MyTable,应用在类上,并且可以指定表名,只有一个值,如下:
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyTable {
String value();
}
再来定义一个@MyColumn注解,用在字段上,也需要一个值,如下:
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyColumn {
String value();
}
在实体对象加上注解
@Data
@MyTable("user_info")
public class User {
@MyColumn("id")
private Integer id;
@MyColumn("user_name")
private String userName;
@MyColumn("nick_name")
private String nickName;
@MyColumn("age")
private Integer age;
@MyColumn("address")
private String address;
@MyColumn("email")
private String email;
}
基本对象有了,那么接下来,需要创建SQL,定义一个query方法,下面粗略的实现,返回字符串即可
package com.cloud.eureka.Practice;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class UserMain {
public static void main(String[] args) throws Exception {
User user = new User();
user.setId(9527);
user.setNickName("华安");
user.setAddress("下沙");
user.setEmail("hello@163.com,hi@qq.com,biu@sina.com");
user.setUserName("HaHaHa");
String sql = query(user);
System.out.println(sql);
}
public static String query(User user) throws Exception {
String SQL_MODEL = "select %s from %s where 1=1%s";
//1. 获取class试验,直接获取User对象,也可以Class.forName()方式
Class c = user.getClass();
//2. 获取Table的名字
boolean b = c.isAnnotationPresent(MyTable.class);
if (!b) {
return "Not Exist Table!";
}
MyTable myTable = (MyTable) c.getAnnotation(MyTable.class);
String tableName = myTable.value();
//3. 获取所有字段
StringBuilder sbField = new StringBuilder();
StringBuilder sbWhere = new StringBuilder();
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
boolean b1 = field.isAnnotationPresent(MyColumn.class);
if (!b1) {
return "Not Exist Field!";
}
//4. 拼接字段
MyColumn myColumn = field.getAnnotation(MyColumn.class);
String columnName = myColumn.value();
sbField.append(columnName).append(",");
//4.1 获取字段的值,先获取get方法,再获取值
String getMethodName = "get" + field.getName().substring(0, 1).toUpperCase() +
field.getName().substring(1);
Method getMethod = c.getMethod(getMethodName);
Object getValue = getMethod.invoke(user);
//5. 拼接where后面的条件
//int基本类型判断
if (getValue == null || (getValue instanceof Integer) && (Integer) getValue == 0) {
continue;
}
sbWhere.append(" and ").append(columnName);
if (getValue instanceof String) {
//in 查询
if (((String) getValue).contains(",")) {
String[] strings = ((String) getValue).split(",");
sbWhere.append(" in(");
for (String str : strings) {
sbWhere.append("'").append(str).append("',");
}
//删除最后一个逗号
sbWhere.deleteCharAt(sbWhere.length() - 1);
sbWhere.append(")");
} else {
//普通查询
sbWhere.append("=").append("'").append(getValue).append("'");
}
} else if (getValue instanceof Integer) {
sbWhere.append("=").append(getValue);
}
}
//拼接完整sql输出
String sql = String.format(SQL_MODEL, sbField.deleteCharAt(sbField.length() - 1),
tableName, sbWhere);
return sql;
}
}
以上针对User做一个试验,字段类型也比较少,可以将入参改成Object或者范型,条件也只加了=与in查询,JDBC就不写了,主要对注解的实践
最后输出: select id,user_name,nick_name,age,address,email from user_info where 1=1 and id=9527 and user_name='HaHaHa' and nick_name='华安' and address='下沙' and email in('hello@163.com','hi@qq.com','biu@sina.com')
总结: 看到一个注解,现在就可以认识注解,知道注解的作用域,应用的场景范围,最后其功能所在,如果在开发中,能实际简化程序,那就再好不过的了
-------------------------------------------------------------------