java反射查询数据库_java反射与注解结合使用(根据传入对象输出查询sql)

本文介绍如何结合Java注解和反射来实现根据对象生成查询数据库的SQL语句。通过自定义@Table和@Column注解标记实体类和字段,利用反射获取并构建查询条件,从而避免硬编码SQL。

我们在项目开发中有很多地方使用到了注解,关于注解的定义与创建小伙伴可以参考我的文章《java注解》。有任何问题的小伙伴们可以在评论区指出哦,欢迎各位大佬指出问题。

今天我要说的是使用注解与反射结合使用,来使我们代码根据优雅,更加高大上(咳,装逼神器啊)。

注解使用@interface 来定义,辣么我们自定义的注解,该使用获取到并且指明该注解的作用呢?java提供了反射机制,通过类的类类型我们可以根据自己需要老操作该类。有管反射的知识,可以参考我的上两章博客。好了,废话不多说,我们上代码:

需求:创建一个与数据库表对应的实体类,通过使用注解的方式,来生成该实体类的查询sql语句。

1.创建Table类注解,用于标明该类对应数据库的表名称

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)public @interfaceTable {

String value();

}

2.创建Column字段注解,用于标明该类中属性与数据库表字段的映射

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;

@Target({ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)public @interfaceColumn {

String value();

}

3.创建实体类,并使用注解Table、Column

/*** 数据库 user表,对应表字段为 userid/username/age/addredd*/@Table("user")public classUser {

@Column("userid")privateString userid;

@Column("username")privateString username;

@Column("age")private intage;

@Column("sl")private doublesl;

@Column("address")privateString address;//添加一个不是数据库的字段: 用于测试

privateString noField;public doublegetSl() {returnsl;

}public void setSl(doublesl) {this.sl =sl;

}publicString getNoField() {returnnoField;

}public voidsetNoField(String noField) {this.noField =noField;

}publicString getUserid() {returnuserid;

}public voidsetUserid(String userid) {this.userid =userid;

}publicString getUsername() {returnusername;

}public voidsetUsername(String username) {this.username =username;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}publicString getAddress() {returnaddress;

}public voidsetAddress(String address) {this.address =address;

}

}

4.创建工具类,根据传入该对象,来生成对应的查询sql

importjava.lang.annotation.Annotation;importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.util.Objects;/*** 注解*/

public classAnnotationUtil {/*** 根据传入的对象 来生成query sql

*

*@paramobject

*@return

*/

public static String getSqlByAnnotation(Object object) throwsException {//使用StringBuilder 线程安全

StringBuilder sb = newStringBuilder();//检查参数是否为空

Objects.requireNonNull(object, "该对象不能为空!");//1.通过反射获取该对象的类类型

Class c =object.getClass();//2.获取该对象的 类注解: 标明表名

boolean table_flag = c.isAnnotationPresent(Table.class);if (!table_flag) {throw newNullPointerException();

}

Table table= (Table) c.getDeclaredAnnotation(Table.class);

sb.append("SELECT * FROM ").append(table.value()).append(" WHERE 1 = 1");//3.获取该对象的 字段注解:显示查询字段

Field[] fields =c.getDeclaredFields();booleanfield_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);

}

}returnsb.toString();

}public static voidmain(String[] args) {

User user= newUser();

user.setUserid("0001");

user.setAge(23);//用于测试没有带Column注解的字段

user.setNoField("field");try{

System.out.println(AnnotationUtil.getSqlByAnnotation(user));

}catch(Exception e) {

e.printStackTrace();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值