在Mybatis当中,可能我们经常会用到在一个方法上加上注解,如:@Insert,@Update,@Delete,@Select,加上这些注解后,框架就能帮助我们执行sql语句,那框架是如何实现的呢?今天笔者就使用注解和反射的知识模拟了一个自动建数据表的功能,当然只是一些简单的代码,重要的是其中的原理。
加入我们现在有一个JavaBean,那么我们如何利用反射和注解实现,让数据库自动帮我们创建一张和该JavaBean对应的数据表呢?
首先我们得弄清楚JavaBean和数据表结构的对应关系:
类对应表,属性对应列,对象对应数据库中表的一条记录,那么创建一张表就需要表名,列名,则我们可以分别在类上加上注解,用来得到表名,在属性上加上注解,得到列名。
具体代码如下:
先定义两个注解:
类上的注解:
package com.tiantang.annotation;
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 类的注解,对应于数据库中的表
* @author LiuJinkun
*
*/
@Target(TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTable {
/**
* 对应数据库的表名
* @return
*/
String value();
}
属性上的注解:
package com.tiantang.annotation; import static java.lang.annotation.ElementType.FIELD; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 属性的注解,对应于数据库中的列 * @author LiuJinkun * */ @Target(FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface MyField { /** * 表的列名 * @return */ String columnName(); /** * 每一列的长度 * @return */ int length(); /** * 列的类型 * @return */ String type(); }
注意,这里在自定义注解时,需要把注解的声明周期设置成RetentionPolicy.RUNTIME,因为反射是在程序运行时才能使用的,因此要想用反射获取到注解,则需要注解在程序运行时还存在着。定义的JavaBean类:
package com.tiantang.annotation; @MyTable("students") public class Student { @MyField(columnName = "student_id", length = 6, type = "int") private int id; @MyField(columnName="name",length=20,type="varchar") private String name; @MyField(columnName="address",length=30,type="varchar") private String address; @MyField(columnName="phone",length=20,type="varchar") private String phone; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
测试类:在测试类中,当程序运行时,利用反射获得类和属性的注解,然后拼接SQL语句:这样SQL语句就拼接完成了,接下来执行sql语句就简单了,读者可以自行测试。这样我们就简单的实现利用反射和注解根据JavaBean的结构来自动建表的功能。当然,在框架里面自动建表大部分都是通过解析XML配置文件来实现的。package com.tiantang.annotation; import java.lang.reflect.Field; public class Client { public static void main(String[] args) throws Exception { //用于拼接sql语句 StringBuffer sql=new StringBuffer(); Class<?> clazz=Class.forName("com.tiantang.annotation.Student"); //获取类上的注解 MyTable myTable=clazz.getAnnotation(MyTable.class); String tableName=myTable.value(); sql.append("CREATE TABLE "+tableName+" ( "); //获取类的属性 Field[] fields=clazz.getDeclaredFields(); for(Field f:fields){ //获取属性上的注解 MyField myField=f.getAnnotation(MyField.class); //拼接sql语句 sql.append(myField.columnName()+" "+myField.type()+"("+myField.length()+"),"); } //因为该sql语句最后会多一个逗号,这里将其删除 sql.deleteCharAt(sql.length()-1); sql.append(")"); //打印sql语句 System.out.println(sql.toString()); } }