zoukankan      html  css  js  c++  java
  • 基于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博客

    img 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)
    @Documented
    public @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

    运行后输出结果:

    User
    user_id
    user_name
    • 1
    • 2
    • 3

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

  • 相关阅读:
    c语言-关键字/标识符
    初识c语言
    MinGW-w64离线安装
    SpringBoot配置文件详解
    JS如何判断是不是为{},以下个人认为是比较好的方法
    IDEA下的SpringBoot工程的如何打包成war包
    cesium之城市行政划分
    cesium之平面裁切
    SSM框架的maven工程使用事务流程
    创建一个最简单的Cesium程序步骤
  • 原文地址:https://www.cnblogs.com/panxuejun/p/7074301.html
Copyright © 2011-2022 走看看