资讯专栏INFORMATION COLUMN

自定义注解实例实现SQL语句生成

lsxiao / 2084人阅读

摘要:如果一种声明使用进行注解,这种类型的注解被作为被标注的程序成员的公共。如果元注解没有出现,那么定义的注解可以应用于程序的任何元素。指明该注解类型被自动继承。指明了该被保留的时间长短。

GitHub

Github地址:AnnoDao

注解的老话题

首先我们要介绍一下注解是什么,有什么用?

java JDK中的几个注解就可以帮助到我们去理解

@Override:重写注解
@Deprecated: 使其无效
@SuppressWarnings: 忽略警告

通过以上几种我们可以大致了解了注解的作用,方便开发,提高逼格,如果你能自定义注解来实现功能那就是又强又牛皮呀!

相关介绍

注解是Annotation,是由元注解定义出来的,元注解有以下几种

@Documented —— 指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API。

@Target——指明该类型的注解可以注解的程序元素的范围。该元注解的取值可以为TYPE,METHOD,CONSTRUCTOR,FIELD等。如果Target元注解没有出现,那么定义的注解可以应用于程序的任何元素。

@Inherited——指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。

@Retention——指明了该Annotation被保留的时间长短。RetentionPolicy取值为SOURCE,CLASS,RUNTIME。

代码演练

需求:

1、方便的对每个字段或字段组合条件进行检索,并打印出sql

分别定义两个注解类

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

    String value();

}

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

    String value();

}

这时直接使用即可

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table("filter")
class Filter {

    @Column("id")
    private int id;

    @Column("user_name")
    private String username;

    @Column("pass_word")
    private String password;

    @Column("age")
    private int age;

    @Column("city")
    private String city;

    @Column("email")
    private String email;

    @Column("mobile")
    private String mobile;

}

主要在注解的反射处理,你需要按照自己的要求去处理业务

public static void main(String[] args) {

        Filter f1 = new Filter();
        f1.setId(10);

        Filter f2 = new Filter();
        f2.setUsername("小龙");

        Filter f3 = new Filter();
        f3.setEmail("123123123@qq.com,llll@qq.com");

        String q1 = query(f1);
        String q2 = query(f2);
        String q3 = query(f3);


        System.out.println(q1);
        System.out.println(q2);
        System.out.println(q3);

    }


    private static String query(Object filter){

        StringBuilder sb = new StringBuilder();
        //1、获取到class
        Class c = filter.getClass();
        //2、获取table的名字
        boolean isexist = c.isAnnotationPresent(Table.class);
        if (!isexist){
            return null;
        }
        Table table = (Table) c.getAnnotation(Table.class);
        String tableName = table.value();

        sb.append("select * from ").append(tableName).append(" where 1=1");

        //3、便利所有字段
        Field[] fields = c.getDeclaredFields();
        for (Field field:fields){
            //4、处理每个字段对应的sql
            //4.1、拿到字段名
            boolean fExist = field.isAnnotationPresent(Column.class);
            if (!fExist){
                continue;
            }
            Column column = field.getAnnotation(Column.class);
            String columnName = column.value();
            //4.2、拿到字段值
            String fieldName = field.getName();
            String getMethodName = "get"+fieldName.substring(0,1).toUpperCase()+
                    fieldName.substring(1);
            Object fieldValue = null;
            try {
                Method getMehtod = c.getMethod(getMethodName);
                fieldValue = getMehtod.invoke(filter);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            //4.3、拼装sql
            if (fieldValue==null || (fieldValue instanceof Integer && (Integer)fieldValue==0)){
                continue;
            }
            sb.append(" and ").append(fieldName);
            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();
    }
效果
select * from filter where 1=1 and id = 10
select * from filter where 1=1 and username = "小龙"
select * from filter where 1=1 and email in( "123123123@qq.com","llll@qq.com")

如果本文对你有所帮助,欢迎关注本人技术公众号,或者点赞,谢谢。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77110.html

相关文章

  • Java 注解入门 生成SQL语句

    摘要:引言在用的时候发现能自动生成,同时带有一些注解,这引起了我的好奇。注解来源于之类的其他语言。关闭不当的编译器警告。允许子类继承父类中的注解。五通过注解反射生成语句接下来,我用一个例子来解释注解的作用。 引言 在用hibernate的时候发现idea能自动生成JavaBean,同时带有一些注解,这引起了我的好奇。当在学习Android的时候,我发现XUtils这个工具包中的DBUtils...

    J4ck_Chan 评论0 收藏0
  • 注解的奇妙之旅

    摘要:注解是弃用不再使用的意思。是处理源码级别的注解,它会生成新的字节码或其它文件。这个该怎么实现呢我们需要在启动之后文件转为字节码文件之前,就需要生成对应的和方法,因为它只在编译期有效。我们在启动后,会根据注解,来创建相应的数据表。 导读 模拟hibernate的注解,创建数据表的源码地址:https://gitee.com/zbone/myanno 注解释义 java开发人员对注解,应该...

    Markxu 评论0 收藏0
  • 面试官都会问的Mybatis面试题,你会这样回答吗?

    摘要:最终能和面试官聊的开心愉快投缘的叫面霸。能够与很好的集成提供映射标签,支持对象与数据库的字段关系映射提供对象关系映射标签,支持对象关系组件维护。使用可以有效的防止注入,提高系统安全性。 showImg(https://segmentfault.com/img/bVbsSlt?w=358&h=269); 一、概述 面试,难还是不难?取决于面试者的底蕴(气场+技能)、心态和认知及沟通技巧。...

    seanHai 评论0 收藏0
  • Java注解详解

    摘要:元注解元注解用于注解其他注解的。该注解表明子类是有继承了父类的注解。在注解中,需要使用四种元注解来声明注解的作用范围生命周期继承,是否生成文档等。另外在注解中也可以有自己的成员变量,如果一个注解没有成员变量则称为标记注解。 在使用SpringBoot作为Web敏捷开发的框架之后,SpringBoot除了自动装配配置的便捷之外,在很多时候需要基于注解来开发。注解不仅增加了代码的可读性,还...

    funnyZhang 评论0 收藏0
  • 使用SpringBoot-JPA进行定义的保存及批量保存

    摘要:既然行不通,或许可以考虑使用注解来自定义一个实现。仍旧提供给了使用者原始的使用方式利用来构造并执行。就像一样,使用者也可以自定义来执行,试试看,同样没有问题,再多的数据也可以被保存到数据库中批量保存的效果达到了。 更多精彩博文,欢迎访问我的个人博客 说明 SpringBoot版本:2.1.4.RELEASE java版本:1.8 文中所说JPA皆指spring-boot-starte...

    boredream 评论0 收藏0

发表评论

0条评论

lsxiao

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<