首页 > 代码库 > 基于java注解实现自己的orm框架

基于java注解实现自己的orm框架

ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系。

现在常见的ORM框架比如Hibernate和mybatis,都是采用了ORM的方式,基本原则就是类-表(Table)、属性-列(Column)这样的对应,所以一个对象就能表示数据表中的一行数据啦。

 

本文转自http://m.blog.csdn.net/woshisangsang/article/details/61916687

CSDN博客

<iframe id="iframeu2901270_0" src="http://pos.baidu.com/vcvm?sz=672x101&rdid=2901270&dc=3&di=u2901270&dri=0&dis=0&dai=1&ps=25x0&dcb=___adblockplus&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1498304831813&ti=%E5%9F%BA%E4%BA%8E%E6%B3%A8%E8%A7%A3%E5%92%8C%E5%8F%8D%E5%B0%84%E7%9A%84Java%20ORM%E6%A1%86%E6%9E%B6(1)-%E9%80%9A%E8%BF%87%E6%B3%A8%E8%A7%A3%E6%8F%8F%E8%BF%B0%E6%98%A0%E5%B0%84%E5%85%B3%E7%B3%BB&ari=2&dbv=0&drs=1&pcs=1024x692&pss=1024x25&cfv=0&cpl=1&chi=1&cce=true&cec=UTF-8&tlm=1498276031&rw=672&ltu=http%3A%2F%2Fm.blog.csdn.net%2Fwoshisangsang%2Farticle%2Fdetails%2F61916687&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DiTytCHNxKyfjwQjIVR3_LmuNZjz8CRxOSo0qa1G5cXX96HWxGAmjGDp9H-8HQZqzGNdzkWP4PjB1nKcZU8pi8eKTYkqO-Wt1QoJBOBvqury%26wd%3D%26eqid%3Dbd0cdfdf0008577e00000006594e504d%26ie%3Dutf-8&ecd=1&uc=748x1024&pis=-1x-1&sr=768x1024&tcn=1498304832&qn=5ca1bf849419db5e&tt=1498304831788.31.32.34" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" align="center,center" width="672" height="101"></iframe>
技术分享 woshisangsang
 

基于注解和反射的Java ORM框架(1)-通过注解描述映射关系

发表于2017/3/13 14:09:39  330人阅读

分类: Java

一,ORM概念

ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关系。

现在常见的ORM框架比如Hibernate和mybatis,都是采用了ORM的方式,基本原则就是类-表(Table)、属性-列(Column)这样的对应,所以一个对象就能表示数据表中的一行数据啦。

二,XML实现简单的ORM映射

使用XML实现简单的ORM映射还是非常直观的,加入有一张用户表结构如下:

技术分享

对应的Java类如下:

package demo;public class User {    private String userId;    private String userName;}
  • 1
  • 2
  • 3
  • 4
  • 5

那么我们可以使用下面的xml描述对象-关系映射(具体的节点名、属性名都是随意设计的,只是为了说明意思):

<?xml version="1.0" encoding="UTF-8"?><!-- orm是所有映射的根节点 --><orm>    <!-- 每对映射使用一个mapping节点 -->    <mapping class="orm.User" table="User">        <property name="userId" column="user_id"/>        <property name="userName" column="user_name"/>    </mapping></orm>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

实际上,有了上面的xml文件,orm.User对象和User表的映射就建立明白了。当ORM框架运作的时候,只需要从xml加载这一个映射关系,就能知道对User对象进行操作时,该对那张表那些列进行操作了。从xml文件中读取数据的方法也有很多,此处不再介绍。

三,自定义注解

之前的xml配置文件是描述映射的,这些描述完全可以使用注解来实现,笔者感觉会更加简洁、直接。

既然是自定义注解,我们首先需要了解哪些是方面是可以自定义的:

1,可以自定义注解应用的元素。Java注解可以应用于包、类(接口)、方法、属性、构造器等,一般常用的也就类(接口)、方法、属性。

2,可以自定义注解使用的时机。比如是否编译的时候就把注解的信息丢掉,比如JVM运行时还是保留注解信息。如果运行时保留的话,就可以通过反射读取注解的内容了,所以自定义注解里面保存的ORM映射信息是可以在程序运行时使用的。

3,是否将注解包含在Javadoc帮助文档里面。

OK,口说太空洞我们来定义一个最简单注解,该注解的作用非常简单,就是说明类与数据库表的映射关系。自定义类使用的关键字是class,自定义注解使用的关键字更加高端的关键字@interface

package demo;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)//该注解用于修饰TYPE元素,也就是修饰类和接口等类型@Retention(RetentionPolicy.RUNTIME)//该注解信息运行时保留@Documented//该注解包含在Javadoc中public @interface Table {//注解名为Table    //此处需要注意,注解中的每个方法表示该注解的一个可配置参数,default表示该配置参数的默认值    public String tableName() default "";}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

将该注解应用于User就是:

package demo;//@Table对应自定义注解,tableName对应自定义注解中的方法,如果只用@Table则表示tableName采用默认的""作为值@Table(tableName="User")public class User {    private String userId;    private String userName;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下来就是需要详细的了解下@Target和@Retention的用法了,因为他俩决定了如何去定义一个注解。

@Target(ElementType.TYPE):表示注解用以修饰类、接口、enum、注解。@Target(ElementType.FIELD):表示注解用以修饰属性@Target(ElementType.METHOD):表示注解用以方法   @Retention(RetentionPolicy.SOURCE):源码之中是有的,编译时候丢弃@Retention(RetentionPolicy.CLASS):编译后.class文件中还有,JVM丢弃之,所以运行时也看不到@Retention(RetentionPolicy.RUNTIME):表示注解运行时可用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

根据以上描述,我们需要自定义两个注解,分别用来描述类-表对应关系及属性-列对应关系,所以全部的源码应为:

//1,Table注解,描述类与表对应package demo;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)//该注解用于修饰TYPE元素,也就是修饰类和接口等类型@Retention(RetentionPolicy.RUNTIME)//该注解信息运行时保留@Documented//该注解包含在Javadoc中public @interface Table {//注解名为Table    //此处需要注意,注解中的每个方法表示该注解的一个可配置参数,default表示该配置参数的默认值    public String tableName() default "";}//2,Column注解,描述属性与列对应package demo;import java.lang.annotation.Documented;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)@Documentedpublic @interface Column {    public String columnName() default "";}//3,注解应用在User类上package demo;//@Table对应自定义注解,tableName对应自定义注解中的方法,如果只用@Table则表示tableName采用默认的""作为值@Table(tableName="User")public class User {    @Column(columnName="user_id")    private String userId;    @Column(columnName="user_name")    private String userName;}
  • 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

四,自定义注解信息的获取

之前分别使用xml和注解描述了User类和User表的对应关系,xml可以通过Java语言文件流等方式直接读取,而注解包含信息该如何读取呢。

既然注解是包含在Java语言中的信息,实际上可以通过反射来读取注解信息,对上述User类中注解读取的方法如下:

package demo;import java.lang.reflect.Field;@Table(tableName="User")public class User {    @Column(columnName="user_id")    private String userId;    @Column(columnName="user_name")    private String userName;    public static void main(String[] args){        Class userClass=User.class;//获取User类信息        if(userClass.isAnnotationPresent(Table.class)){//判断userClass是否使用了Table注解            Table table=(Table)userClass.getAnnotation(Table.class);//获取注解信息            System.out.println(table.tableName());//输出Table注解的tableName参数        }        Field[] fields = userClass.getDeclaredFields();        for(Field field:fields){//遍历属性            if(field.isAnnotationPresent(Column.class)){//具备Column注解                Column column=(Column)field.getAnnotation(Column.class);//获取注解信息                System.out.println(column.columnName());            }        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

运行后输出结果:

Useruser_iduser_name
  • 1
  • 2
  • 3

可见通过反射,可以轻易的获取注解的信息。

基于java注解实现自己的orm框架