java反射与注解结合使用(根据传入对象输出查询sql)
程序员文章站
2022-08-11 14:06:44
我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《java注解》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。 今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。 注解使用@interface 来定义,辣么我 ......
我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。
今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。
注解使用@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(); } } }