我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《java注解》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。
今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。
注解使用@interface 来定义,辣么我们自定义的注解,该使用获取到并且指明该注解的作用呢?java提供了反射机制,通过类的类类型我们可以根据自己需要老操作该类。有管反射的知识,可以参考我的上两章博客。好了,废话不多说,我们上代码:
需求:创建一个与数据库表对应的实体类,通过使用注解的方式,来生成该实体类的查询sql语句。
1.创建Table类注解,用于标明该类对应数据库的表名称
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(); }
2.创建Column字段注解,用于标明该类中属性与数据库表字段的映射
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(); }
3.创建实体类,并使用注解Table、Column
/** * 数据库 user表,对应表字段为 userid/username/age/addredd */ @Table("user") public class User { @Column("userid") private String userid; @Column("username") private String username; @Column("age") private int age; @Column("sl") private double sl; @Column("address") private String address; // 添加一个不是数据库的字段: 用于测试 private String noField; public double getSl() { return sl; } public void setSl(double sl) { this.sl = sl; } public String getNoField() { return noField; } public void setNoField(String noField) { this.noField = noField; } public String getUserid() { return userid; } public void setUserid(String userid) { this.userid = userid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
4.创建工具类,根据传入该对象,来生成对应的查询sql
import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Objects; /** * 注解 */ public class AnnotationUtil { /** * 根据传入的对象 来生成query sql * * @param object * @return */ public static String getSqlByAnnotation(Object object) throws Exception { // 使用StringBuilder 线程安全 StringBuilder sb = new StringBuilder(); // 检查参数是否为空 Objects.requireNonNull(object, "该对象不能为空!"); // 1.通过反射获取该对象的类类型 Class c = object.getClass(); // 2.获取该对象的 类注解: 标明表名 boolean table_flag = c.isAnnotationPresent(Table.class); if (!table_flag) { throw new NullPointerException(); } Table table = (Table) c.getDeclaredAnnotation(Table.class); sb.append("SELECT * FROM ").append(table.value()).append(" WHERE 1 = 1"); // 3.获取该对象的 字段注解:显示查询字段 Field[] fields = c.getDeclaredFields(); boolean field_flag; Column column; String field_name; Method menthod; Object val; for (Field field : fields) { // 首先得拿到字段名称:通过字段上的注解标明该指定是数据库表对应的字段 field_flag = field.isAnnotationPresent(Column.class); if (!field_flag) { continue; } column = field.getDeclaredAnnotation(Column.class); // 其次得拿到字段值 : 通过反射调用类的getXxxx方法 field_name = field.getName(); menthod = c.getDeclaredMethod("get" + Character.toUpperCase(field_name.charAt(0)) + field_name.substring(1)); val = menthod.invoke(object); // 判断该字段是否为空,不为空,才进行append // 这里要注意:有些属性不赋值时候,java会自动生成默认值,如Double默认为0.0 // 还有其他类型,小伙伴们可以自行测试 if (!Objects.isNull(val)) { if((val instanceof Double) && (double) val == 0.0){ continue; } sb.append(" AND ").append(column.value()).append(" = "); sb.append(val); } } return sb.toString(); } public static void main(String[] args) { User user = new User(); user.setUserid("0001"); user.setAge(23); // 用于测试没有带Column注解的字段 user.setNoField("field"); try { System.out.println(AnnotationUtil.getSqlByAnnotation(user)); } catch (Exception e) { e.printStackTrace(); } } }
原文地址:https://www.cnblogs.com/www-123456/p/10887576.html
时间: 2024-10-12 03:42:19