1、实现功能
我们已经对注解有了基本的认识,知道了如何自定义注解,如何使用和最基本的处理注解。
本篇主要介绍,如何使用运行时级别的注解,配合反射来自动生成建表的sql语句。如下例:
我们有实体类Student,并添加相应的注解 @Table、@Column,最终可以获取到创建对应表的sql语句
@Table(name = "t_student")
public class Student {
@Column(name = "c_name")
public String name;
@Column(name = "c_sex")
public String sex;
...
}11
1
(name = "t_student") 2
public class Student {3
4
(name = "c_name")5
public String name;6
7
(name = "c_sex")8
public String sex;9
10
...11
}2、自定义注解
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
//设置表名
String name();
}
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
//设置字段名
String name();
}11
1
(RetentionPolicy.RUNTIME)2
public @interface Table {3
//设置表名4
String name();5
}6
7
(RetentionPolicy.RUNTIME)8
public @interface Column {9
//设置字段名10
String name();11
}3、对实体类使用注解
/**
* 学生类
*/
@Table(name = "t_student")
public class Student {
@Column(name = "c_name")
public String name;
@Column(name = "c_sex")
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}28
1
/**2
* 学生类3
*/4
(name = "t_student")5
public class Student {6
7
(name = "c_name")8
public String name;9
10
(name = "c_sex")11
public String sex;12
13
public String getName() {14
return name;15
}16
17
public void setName(String name) {18
this.name = name;19
}20
21
public String getSex() {22
return sex;23
}24
25
public void setSex(String sex) {26
this.sex = sex;27
}28
}4、运行时获取注解并转化
4.1 获取表名
private static String getTableName(Class<?> clazz) {
String name = null;
//如果有@Table注解
if (clazz.isAnnotationPresent(Table.class)) {
Table table = clazz.getAnnotation(Table.class);
name = table.name();
}
return name;
}10
1
private static String getTableName(Class<?> clazz) {2
String name = null;3
//如果有@Table注解4
if (clazz.isAnnotationPresent(Table.class)) {5
Table table = clazz.getAnnotation(Table.class);6
name = table.name();7
}8
9
return name;10
}4.2 获取字段名和类型
4.2.1 建立NameAndType类用来封装获取到的字段名和类型
public class NameAndType {
String name;
String type;
public NameAndType(String name, String type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}27
1
public class NameAndType {2
3
String name;4
5
String type;6
7
public NameAndType(String name, String type) {8
this.name = name;9
this.type = type;10
}11
12
public String getName() {13
return name;14
}15
16
public void setName(String name) {17
this.name = name;18
}19
20
public String getType() {21
return type;22
}23
24
public void setType(String type) {25
this.type = type;26
}27
}4.2.2 获取字段名和类型
private static List<NameAndType> getColumns(Class<?> clazz) throws Exception {
List<NameAndType> colums = new ArrayList<NameAndType>();
Field[] fields = clazz.getDeclaredFields();
if (fields != null) {
//分析clazz中变量是否需要生成sql字段
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
//生成sql字段的字段名
Column column = field.getAnnotation(Column.class);
String name = column.name();
//生成sql字段的字段类型
String type;
if (int.class.isAssignableFrom(field.getType())) {
type = "integer";
}
else if (String.class.isAssignableFrom(field.getType())) {
type = "text";
}
else {
throw new Exception("unsupported type");
}
colums.add(new NameAndType(name, type));
}
}
}
return colums;
}28
1
private static List<NameAndType> getColumns(Class<?> clazz) throws Exception {2
List<NameAndType> colums = new ArrayList<NameAndType>();3
Field[] fields = clazz.getDeclaredFields();4
if (fields != null) {5
//分析clazz中变量是否需要生成sql字段6
for (Field field : fields) {7
if (field.isAnnotationPresent(Column.class)) {8
//生成sql字段的字段名9
Column column = field.getAnnotation(Column.class);10
String name = column.name();11
//生成sql字段的字段类型12
String type;13
if (int.class.isAssignableFrom(field.getType())) {14
type = "integer";15
}16
else if (String.class.isAssignableFrom(field.getType())) {17
type = "text";18
}19
else {20
throw new Exception("unsupported type");21
}22
colums.add(new NameAndType(name, type));23
}24
}25
}26
27
return colums;28
}注意Class类的isAssignableFrom方法可以判断两个类是不是存在父子关系。
4.3 生成建表sql
public static String createTable(Class<?> clazz) throws Exception {
String sql = null;
String tableName = getTableName(clazz);
List<NameAndType> columns = getColumns(clazz);
if (tableName != null && !tableName.equals("") && !columns.isEmpty()) {
StringBuffer strBuffer = new StringBuffer("CREATE TABLE " + tableName + "( ");
for (NameAndType column : columns) {
String bean = column.getName() + " " + column.getType() + ", ";
strBuffer.append(bean);
}
//删除最后多余的一个逗号
strBuffer.deleteCharAt(strBuffer.length() - 2);
strBuffer.append(");");
sql = strBuffer.toString();
}
return sql;
}19
1
public static String createTable(Class<?> clazz) throws Exception {2
String sql = null;3
String tableName = getTableName(clazz);4
List<NameAndType> columns = getColumns(clazz);5
6
if (tableName != null && !tableName.equals("") && !columns.isEmpty()) {7
StringBuffer strBuffer = new StringBuffer("CREATE TABLE " + tableName + "( ");8
for (NameAndType column : columns) {9
String bean = column.getName() + " " + column.getType() + ", ";10
strBuffer.append(bean);11
}12
//删除最后多余的一个逗号13
strBuffer.deleteCharAt(strBuffer.length() - 2);14
strBuffer.append(");");15
sql = strBuffer.toString();16
}17
18
return sql;19
}4.4 测试和结果
public class TestAnnotation {
public static void main(String[] args) throws Exception {
String sql = TableAnnotationUtil.createTable(Student.class);
System.out.println(sql);
}
}
//结果输出
CREATE TABLE t_student( c_name text, c_sex text );x
1
public class TestAnnotation {2
public static void main(String[] args) throws Exception {3
String sql = TableAnnotationUtil.createTable(Student.class);4
System.out.println(sql);5
}6
}7
8
//结果输出9
CREATE TABLE t_student( c_name text, c_sex text );