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
@Table(name = "t_student") 
2
public class Student {
3

4
    @Column(name = "c_name")
5
    public String name;
6

7
    @Column(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
@Retention(RetentionPolicy.RUNTIME)
2
public @interface Table {
3
    //设置表名
4
    String name();
5
}
6

7
@Retention(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
@Table(name = "t_student")
5
public class Student {
6

7
    @Column(name = "c_name")
8
    public String name;
9

10
    @Column(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 );

5、参考链接

附件列表

[04] 利用注解生成实体类对应的建表sql语句的更多相关文章

  1. 阶段3 1.Mybatis_12.Mybatis注解开发_5 mybatis注解建立实体类属性和数据库表中列的对应关系

    创建新项目,一对多 复制刚才关闭的项目的文件 复制到们的新项目里面 复制包的依赖 删减相关代码.只保留这三个查询的方法 模糊查询改成传统的占位符的方式 之前是可以自定义实体类的属性字段,和数据库的字典 ...

  2. 通过实体类生成建表SQL语句实现方法

    import java.io.File; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.ut ...

  3. 提升开发效率的notepad++一些快捷方法(实体类的创建和查询sql语句的编写)

    新手要创建数据库表中,对应字段名的实体类,是不是感觉很麻烦,可以用notepad++快速的把实体类中的字段名进行排版,随后直接粘入idea使用 下面是navicat的演示 选择一个表,右键选择设计表 ...

  4. IDEA03 连接数据库、自动生成实体类

    1 版本说明 JDK:1.8 MAVEN:3.5 SpringBoot:2.0.4 IDEA:旗舰版207.2 MySQL:5.5 2 利用IDEA连接数据库 说明:本案例以MySQL为例 2.1 打 ...

  5. eclipse逆向生成实体类注解方式或者xml方式

    转载自:http://www.2cto.com/database/201501/372023.html http://blog.csdn.net/wangpeng047/article/details ...

  6. 利用org.mybatis.generator生成实体类

    springboot+maven+mybatis+mysql 利用org.mybatis.generator生成实体类 1.添加pom依赖:   2.编写generatorConfig.xml文件 ( ...

  7. 使用hibernate利用实体类生成表和利用表生成实体类

    1,配置数据库,这里以oracle数据库为例.点击右侧Database图标:

  8. Myeclipse 10使用hibernate生成注解(annotation)实体类

    以MySQL数据库为例,请在数据库里面建好对应的表. 1.配置数据库链接 打开Myelipse Database Explorer视图 Window-->Open Perspective--&g ...

  9. Hibernate框架学习之注解映射实体类

         前面的相关文章中,我们已经介绍了使用XML配置文件映射实体类及其各种类型的属性的相关知识.然而不论是时代的潮流还是臃肿繁杂的配置代码告诉我们,注解配置才是更人性化的设计,于是学习了基本的映射 ...

随机推荐

  1. 一步步学习操作系统(1)——参照ucos,在STM32上实现一个简单的多任务(“啰里啰嗦版”)

    该篇为“啰里啰嗦版”,另有相应的“精简版”供参考 “不到长城非好汉:不做OS,枉为程序员” OS之于程序员,如同梵蒂冈之于天主教徒,那永远都是块神圣的领土.若今生不能亲历之,实乃憾事! 但是,圣域不是 ...

  2. fis3+vue+pdf.js制作预览PDF文件或其他

    人生第一篇博客,的确有点紧张,但有些许兴奋,因为这对于我来说应该是一个好的开始,以此励志在技术的道路上越走越远. 看过了多多少少的技术博客,给自己带来了很多技术上的收获,也因此在想什么时候自己也可以赠 ...

  3. 递归调用里的性能问题(js)

    说明 这是在codewars.com上刷的一道js练习题,在此做个记录 问题描述 The Fibonacci sequence is traditionally used to explain tre ...

  4. 34、锁问题与线程queue

    上一篇随笔我们学了全局解释器锁,前面也学了互斥锁,今天学习一些与锁相关的点,例如递归锁,信号量,Event,还会学习我们已经很熟悉的队列,不过这次的队列是作为一个模块出现的. 一.同步锁 1.join ...

  5. SpringMVC简单配置

    SpringMVC简单配置 一.eclipse安装Spring插件 打开help下的Install New Software 点击add,location中输入http://dist.springso ...

  6. 基于SSM实现的简易员工管理系统(网站上线篇)

    经历无数苦难,好不容易,网站终于上线了.=.=内牛满面ing.chengmingwei.top就是本员工管理系统的主页啦.是的,很简陋,但是毕竟是第一次嘛,所以慢慢来嘛. 如上次所说的(网站简介,见: ...

  7. 10分钟搞懂Tensorflow 逻辑回归实现手写识别

    1. Tensorflow 逻辑回归实现手写识别 1.1. 逻辑回归原理 1.1.1. 逻辑回归 1.1.2. 损失函数 1.2. 实例:手写识别系统 1.1. 逻辑回归原理 1.1.1. 逻辑回归 ...

  8. java对象 深度克隆(不实现Cloneable接口)和浅度克隆

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt128 为什么需要克隆: 在实际编程过程中,我们常常要遇到这种情况:有一个对象 ...

  9. Servlet和JSP生命周期概述

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt374 Servlet生命周期分为三个阶段: 1,初始化阶段  调用init( ...

  10. PowerBI入门 第三篇:报表设计技巧

    最近做了几个PowerBI报表,对PowerBI的设计有了更深的理解,对数据的塑形(sharp data),不仅可以在Data Source中实现,例如在TSQL查询脚本中,而且可以在PowerBI中 ...