用注解编写创建表的SQL语句

时间:2022-08-30 15:18:59

今晚读了think in java 的章节,感觉很不错,我就敲了下来,贴上代码给以后一个回顾: 

建议提前读一下think in java 注解 。 

说明创建注解我在第一个注解说明下,以后的注解不在说明。‘ 

DBTable 注解: 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
* Project Name:myannotation
* File Name:DBTable.java
* Package Name:com.iflytek.db
* Date:2016-8-28下午08:20:54
* Copyright (c) 2016, syzhao@iflytek.com All Rights Reserved.
*
*/
 
package com.iflytek.db;
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
@Target:
   @Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。
  作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
  取值(ElementType)有:
    1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
 
 @Retention:
  @Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
  作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
  取值(RetentionPoicy)有:
    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)
  Retention meta-annotation类型有唯一的value作为成员,它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable
{
  public String name() default "";
}

Constraints 约束注解: 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Project Name:myannotation
* File Name:Constraints.java
* Package Name:com.iflytek.db
* Date:2016-8-28下午08:27:08
* Copyright (c) 2016, syzhao@iflytek.com All Rights Reserved.
*
*/
 
package com.iflytek.db;
 
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 Constraints
{
  boolean primaryKey() default false;
  
  boolean allowNull() default true;
  
  boolean unique() default false;
}

 SQLInteger int注解: 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Project Name:myannotation
* File Name:SQLInteger.java
* Package Name:com.iflytek.db
* Date:2016-8-29下午10:24:11
* Copyright (c) 2016, syzhao@iflytek.com All Rights Reserved.
*
*/
 
package com.iflytek.db;
 
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 SQLInteger
{
  String name() default "";
  
  Constraints constraints() default @Constraints;
}

 SQLString 字符注解: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Project Name:myannotation
* File Name:SQLString.java
* Package Name:com.iflytek.db
* Date:2016-8-29下午10:28:04
* Copyright (c) 2016, syzhao@iflytek.com All Rights Reserved.
*
*/
 
package com.iflytek.db;
 
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 SQLString
{
  int value() default 0;
  
  String name() default "";
  
  Constraints constraints() default @Constraints;
}

 创建表的处理器:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* Project Name:myannotation
* File Name:TableCreator.java
* Package Name:com.iflytek.table
* Date:2016-8-29下午10:57:52
* Copyright (c) 2016, syzhao@iflytek.com All Rights Reserved.
*
*/
 
package com.iflytek.table;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
 
import com.iflytek.db.Constraints;
import com.iflytek.db.DBTable;
import com.iflytek.db.SQLInteger;
import com.iflytek.db.SQLString;
 
public class TableCreator
{
  public static void main(String[] args)
  {
    createTable(Member.class);
  }
  
  //创建表SQL语句
  private static void createTable(Class<?> cl)
  {
    //获取DBTable注解
    DBTable dbTable = cl.getAnnotation(DBTable.class);
    //判断DBTable注解是否存在
    if (dbTable == null)
    {
      System.out.println("没有找到关于DBTable");
      return;
    }
    
    //如果@DBTable注解存在获取表明
    String tableName = dbTable.name();
    //判断表名是否存在
    if (tableName.length() < 1)
    {
      //不存在,说明默认就是类名,通过 cl.getSimpleName()获取类名并且大写
      tableName = cl.getSimpleName().toUpperCase();
    }
    
    //定义获取column的容器
    List<String> columnDefs = new ArrayList<String>();
    //循环属性字段
    //说明:getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
    //getFields()获得某个类的所有的公共(public)的字段,包括父类。
    for (Field field : cl.getDeclaredFields())
    {
      //定义表字段名称变量
      String columnName = null;
      //获取字段上的注解(现在字段允许多个注解,因此返回的是数组)
      Annotation[] anns = field.getDeclaredAnnotations();
      //判断属性是否存在注解
      if (anns.length < 1)
        continue;
      
      //判断是否是我们定义的数据类型
      if (anns[0] instanceof SQLInteger)
      {
        //获取SQLInteger 注解
        SQLInteger sInt = (SQLInteger)anns[0];
        //判断是否注解的name是否有值
        if (sInt.name().length() < 1)
        {
          //如果没有值,说明是类的属性字段,获取属性并转换大写
          columnName = field.getName().toUpperCase();
        }
        else
        { //如果有值,获取设置的name值
          columnName = sInt.name();
        }
        //放到属性的容器内
        columnDefs.add(columnName + " INT " + getConstraints(sInt.constraints()));
      }
      
      //同上SQLInteger,这里不写注释了
      if (anns[0] instanceof SQLString)
      {
        SQLString sString = (SQLString)anns[0];
        if (sString.name().length() < 1)
        {
          columnName = field.getName().toUpperCase();
        }
        else
        {
          columnName = sString.name();
        }
        columnDefs.add(columnName + " VARCHAR(" + sString.value() + ")" + getConstraints(sString.constraints()));
      }
      
      //定义生成创建表的SQL语句
      StringBuilder createCommand = new StringBuilder("CREATE TABLE " + tableName + "(");
      //循环上面属性容器,
      for (String columnDef : columnDefs)
      {
        //把属性添加到sql语句中
        createCommand.append("\n  " + columnDef + ",");
        //去掉最后一个逗号
        String tableCreate = createCommand.substring(0, createCommand.length() - 1) + ");";
        //打印
        System.out.println("Table creation SQL for " + cl.getName() + " is :\n" + tableCreate);
      }
    }
  }
  
  private static String getConstraints(Constraints con)
  {
    String constraints = "";
    //判断是否为null
    if (!con.allowNull())
    {
      constraints += " NOT NULL ";
    }
    //判断是否是主键
    if (con.primaryKey())
    {
      constraints += " PRIMARY KEY ";
    }
    //是否唯一
    if (con.unique())
    {
      constraints += " UNIQUE ";
    }
    
    return constraints;
  }
}

以上代码拷贝出来,就可以运行了! 

上面虽然是简单的创建表语句,但我们可以蔓延到hibernate的domain类里的注解,各种CURD ,何尝不是这样处理的呢,只是hibernate有很多东西,但是万变不离其宗,以后有机会研究一下hibernate 。 

收获: 

读了以后,对于注解知道为什么要这么用了,其实顾名思义就是一个注解,只是有一个处理器来处理这个注解,这对我以后用到注解方面应该有帮助的, 

时间不早了,就写到这里!

结果:

用注解编写创建表的SQL语句

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。