注解实战
项目需求
项目说明:项目取自一个公司的持久层架构,用来代替Hibernate的解决方案,核心代码就是通过注解来实现的。需求:
1)有一张用户表,字段包括用户ID,用户名,昵称,年龄,性别,所在城市,邮箱,手机号。
2)方便的对每个字段或字段的组合条件进行检索,并打印出SQL语句。
3)使用方式要足够简单。
实战代码:
自定义注解@Table
package com.demo.dao;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String value();
}
自定义注解@Column
package com.demo.dao;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String value();
}
实体类User:
package com.demo.dao;
@Table("user")
public class User {
@Column("id")
private int id;
@Column("user_name")
private String username;
@Column("nick_name")
private String nickname;
@Column("age")
private int age;
@Column("city")
private String city;
@Column("email")
private String email;
@Column("mobile")
private String mobile;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
}
测试类Test:
package com.demo.dao;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
User user1 = new User();
user1.setId(0001);//查询ID为0001的用户
user1.setNickname("繁华");//查询昵称为繁华的用户
User user2 = new User();
user2.setUsername("Jack");//查询用户名为Jack的用户
user2.setAge(18);//查询年龄为18的用户
User user3 = new User();
user3.setEmail("lian@sina.com,jiang@qq.com");//查询邮箱为其中任意一个的用户
String sql1 = query(user1);
String sql2 = query(user2);
String sql3 = query(user3);
System.out.println(sql1);
System.out.println(sql2);
System.out.println(sql3);
}
private static String query(User user){
StringBuilder sb = new StringBuilder();
//1.获取到Class
Class< ?> class1 = user.getClass();
//2.获取到table的名字
boolean flag1 = class1.isAnnotationPresent(Table.class);
if(!flag1){
return null;
}
Table table = (Table)class1.getAnnotation(Table.class);
String tableName = table.value();
sb.append("select * from ").append(tableName).append(" where 1=1");
//3.遍历所有的字段
Field[] fields = class1.getDeclaredFields();
for (Field field : fields) {
//4.处理每个字段对应的sql
//拿到字段名
boolean flag2 = field.isAnnotationPresent(Column.class);
if (!flag2) {
continue;
}
Column column = field.getAnnotation(Column.class);
String columnName = column.value();
//拿到字段值
String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Object fieldValue = null;
try {
Method getMethod = class1.getMethod(getMethodName);
fieldValue = getMethod.invoke(user);
} catch (Exception e) {
e.printStackTrace();
}
//拼装sql
if(fieldValue == null || (fieldValue instanceof Integer && (Integer)fieldValue == 0)){
continue;
}
sb.append(" and ").append(columnName);
if(fieldValue instanceof String){
if(((String)fieldValue).contains(",")){
String[] values = ((String)fieldValue).split(",");
sb.append(" in(");
for (String value : values) {
sb.append("'").append(value).append("'").append(",");
}
sb.deleteCharAt(sb.length()-1);
sb.append(")");
}else {
sb.append(" = ").append("'").append(fieldValue).append("'");
}
}else if(fieldValue instanceof Integer) {
sb.append(" = ").append(fieldValue);
}
}
return sb.toString();
}
}
测试结果:
这里只是大概了解一下持久层框架底层是怎么做到的,就是封装JDBC代码。