初入 java 注解(三)拼装SQL语句

来源

本篇代码抽取自一个公司的持久层框架,用来代替 Hibernate 的解决方案,核心代码是通过注解来实现的。


需求

1、有一张学生表,字段包括学号、学生名字、性别、手机号码、所在城市。
2、便捷地对每个字段或字段的组合条件进行检索,并打印出SQL语句。


编码

1、编写 Student 类

public class Student {
    
    private int ID;
    private String name;
    private boolean sex;
    private String phone;
    private String address;

    //省略getter和setter
}

2、编写 Test 类

public class Test {

    public static void main(String[] args) {

        Student stu1 = new Student();
        stu1.setID(12345678);//查询学号为12345678的学生
        Student stu2 = new Student();
        stu2.setName("pm");//查询学生名为pm的学生
        Student stu3 = new Student();
        stu3.setAddress("青岛市,北京市");//查询地址为任意其中一个的学生

        String sql1 = query(stu1);
        String sql2 = query(stu2);
        String sql3 = query(stu3);

        System.out.println(sql1);
        System.out.println(sql2);
        System.out.println(sql3);
    }

    private static String query(Student stu) {

        return null;
    }
}

3、考虑代码怎么样与数据库进行映射,利用 Student 类最合适不过,我们进行修改:

@Table("student")
public class Student {

    @Column("id")
    private int ID;

    @Column("name")
    private String name;

    @Column("sex")
    private boolean sex;

    @Column("phone")
    private String phone;

    @Column("address")
    private String address;

	//省略getter和setter
}

这里使用到了 Table 和 Column 两个自定义注解,要注意作用域不同:

Table

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    String value();
}

Column

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    String value();
}

4、考虑实现测试类的 query 方法

private static String query(Object object) {
        StringBuilder sb = new StringBuilder();

        Class mClass = object.getClass();
        boolean isExist = mClass.isAnnotationPresent(Table.class);
        if (!isExist)
            return null;
        Table table = (Table) mClass.getAnnotation(Table.class);
        String tabName = table.value();
        //拼装SQL表名
        sb.append("select * from ").append(tabName).append(" where 1=1");

        //获取类的所有字段
        Field[] fields = mClass.getDeclaredFields();
        for (Field f : fields) {
            //下面代码获取字段注解
            boolean isFExist = f.isAnnotationPresent(Column.class);
            if (!isFExist) {
                continue;
            }
            Column column = f.getAnnotation(Column.class);
            String columnName = column.value();

            //下面代码获取字段值
            Object filedValue = null;
            try {
                //PropertyDescriptor 类表示JavaBean类通过存储器导出一个属性
                PropertyDescriptor pd = new PropertyDescriptor(f.getName(), mClass);
                //getReadMethod() 获得用于读取属性值的方法,即getter方法
                Method method = pd.getReadMethod();
                //通过反射调用getter方法
                filedValue = method.invoke(object);
            } catch (Exception e) {
                e.printStackTrace();
            }

            //拼装SQL条件
            if (filedValue == null || (filedValue instanceof Integer && (Integer) filedValue == 0)) {
                continue;
            }
            sb.append(" and ").append(columnName);
            if (filedValue instanceof String) {
                //包含多段
                if (((String) filedValue).contains(",")) {
                    String[] arr = ((String) filedValue).split(",");
                    sb.append(" in(");
                    for (String str : arr) {
                        sb.append("'").append(str).append("'").append(",");
                    }
                    sb.deleteCharAt(sb.length() - 1).append(")");
                } else {
                    sb.append("=").append("'").append(filedValue).append("'");
                }
            } else if (filedValue instanceof Boolean) {
                sb.append("=").append("'").append(filedValue).append("'");
            } else if (filedValue instanceof Integer) {
                sb.append("=").append(filedValue);
            }
        }//end for
        return sb.toString();
    }//end query

打印:

select * from student where 1=1 and s_id=12345678 and s_sex='false'
select * from student where 1=1 and s_name='pm' and s_sex='false'
select * from student where 1=1 and s_sex='false' and s_address in('青岛市','北京市')

小结

此例子是将实体类类名注解映射成数据库的表名,将实体类的字段名注解映射成数据库的字段名。从而进行解析实体类的注解,达到快速拼装SQL语句的效果。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java通过反射注解对应SQL语句的步骤如下: 1. 定义注解:首先需要定义一个注解,该注解用于标识字段信息,例如字段名、字段类型、是否为主键等信息。 ``` @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { String name(); // 字段名 String type(); // 字段类型 boolean primaryKey() default false; // 是否为主键 } ``` 2. 定义实体类:在实体类的字段上使用上面定义的注解。 ``` public class User { @Column(name = "id", type = "int", primaryKey = true) private int id; @Column(name = "name", type = "varchar") private String name; @Column(name = "age", type = "int") private int age; // 省略getter和setter方法 } ``` 3. 通过反射获取实体类的字段信息:通过反射获取实体类的字段信息,然后读取字段上的注解,获取字段名、字段类型和是否为主键等信息。 ``` public static <T> String generateCreateTableSql(Class<T> clazz) { StringBuilder sb = new StringBuilder(); sb.append("CREATE TABLE IF NOT EXISTS "); sb.append(clazz.getSimpleName()); sb.append("("); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); sb.append(column.name()); sb.append(" "); sb.append(column.type()); if (column.primaryKey()) { sb.append(" PRIMARY KEY"); } sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(")"); return sb.toString(); } ``` 4. 生SQL语句:将读取到的字段信息拼接对应SQL语句,例如创建表、插入数据、更新数据等。 ``` public static <T> String generateInsertSql(T entity) { StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO "); sb.append(entity.getClass().getSimpleName()); sb.append("("); Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { Column column = field.getAnnotation(Column.class); sb.append(column.name()); sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(") VALUES ("); for (Field field : fields) { if (field.isAnnotationPresent(Column.class)) { field.setAccessible(true); Object value = field.get(entity); if (value instanceof String) { sb.append("'"); sb.append(value); sb.append("'"); } else { sb.append(value); } sb.append(","); } } sb.deleteCharAt(sb.length() - 1); sb.append(")"); return sb.toString(); } ``` 以上就是利用反射注解对应SQL语句的步骤,可以根据需要进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值