好久都没有更新博客了,来学校之后一大堆的事.第一个星期完成物品管理系统的第一版,连续7,8天都从早上写代码到熄灯,三天时间学会Bootstrap,写前台,三天时间写后台,再有两天debug.第二个星期都忘了弄了什么了,第三个星期又忙着弄实习简历,现在终于有时间写点东西了.
跟我一起写ORM,主要是针对之前我参考了JFinal和ETMVC部分源码写的一个叫qm86-ar的简单的ORM,源码已经上传GitHub(这里是链接)上了.由于之前有用Hibernate之类的ORM,觉得配置比较麻烦,JFinal的ORM部分又不够灵活,JFinal里Model中的对象属性名必须与DB中表的属性名字一样,这样的设计让我这个喜欢把列名写得很长的人感到很尴尬,要取值的时候还得写一长串的名字我实在受不了了.所以在挣扎了一段时间后我决定自己写一个ORM,于是乎需求来了.
功能需求:
-
ORM,映射数据库表
-
基本的CRUD
-
声明式创建映射对象和对象属性,可以自由设置对象和属性的名字
-
声明式事务
举个例子说,就是像下面写的这样:
@Table(name = "tb_TestTable")
public class TestTable extends ActiveRecordBase{
@Id(name = "tb_id")
private int id;
@Column
private String name;
@Column(name = "address")
private String where;
@Column
private java.util.Date when;
(Some getters and setters)
}
@Table标注用来声明表映射到的model对象,表名为tb_testtable,由@Table的name属性指定,如果不写name属性,则缺省的以model对象的名字来查询数据库的表
@Id标注用来声明表中的主键,如果不写name属性则缺省以所声明的变量名为主键查询,上面例子中,如果把(name = "tb_id")删除,ORM就认为id是表中的主键名
@Column标注用来声明表中除主键外其它列的名字,用法和@Id相同
此外还有一些@ManyToOne,@OneToOne,@OneToMany标注以后再说吧
那如果实现标注声明呢?看看我写的源码在com.qm86.ar.annotation包下包含的就是标注的代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "_null";
}
这里标注的修饰也是用标注来实现的(汗~~).要对声明一个标注需要用@interface关键字,注意不是interface哦.
@interface上面的@Target标注是用来说明你所声明的标注(Column)修饰对象的范围,若为ElementType.FIELD,说明这个标注Column可以用来声明成员变量,若是ElememtType.METHOD自然是用来声明方法,ElementType.TYPE用来声明类,接口或者是枚举类型,参照上例的@Table,其它的看看API就懂了,@Target还可以有多种修饰例如@Target(ElementType.FIELD,ElememtType.METHOD)
@Retention定义了这个标注被保留的时长,有些标注只出现在源码中用RetentionPolicy.SOURCE修饰,编译源码时并不编译到它,有些标注只存在.class文件中用RetentionPolicy.CLASS修饰,JVM并不运行它,默认情况下用的是这种修饰,还有些标注JVM可以运行它,它可以用作反射机制中,它用RetentionPolicy.RUNTIME修饰.啥是反射机制?哈哈,慢慢来,我们马上就要讲到了.
现在标注声明好了,我们还可以为标注添加属性,来看上例中String name() default "_null"就是Column标注的一个属性,你也许会感到疑惑,声明的属性怎么还带有()?它是个方法吗?NONONO,它是一个变量,类型是String,java在这里允许这个变量后有(),并且可以给它设一个默认值,用default.用不加那个()可以不?我测试过是可以的,只是设默认值时不能和default,必须用=.加()的好处?我也不知道…我估计是在调用这个属性时用()看上去会舒服点?getAnnotation(Column.class).name和getAnnotation(Column.class).name()(顺便吐槽一下C#,我到现在还弄不清楚C#里访问属性的时什么时候用()什么时候不用…).
若这个属性的名字是value时,调用标注来声明的时候可以简写,比如
public @interface Column {
String value();
}
调用时可以用@Column(value = "xxxx")也可以@Column("xxxx"),注意在调用时属性是不能带()的,不能写成@Column(name() = "XXX")
现在你就可以调用标注声明了,先讲到这吧,后面一节要讲的是反射机制哦~