深入理解Java的Annotation系列-第五部分 使用注解编写ORM框架

来源:互联网 发布:白兔商标查询软件 编辑:程序博客网 时间:2024/05/22 19:23

一、什么是ORM?

    对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/Rmapping),是一种程序技术,随着面向对象的软件开发方法发展而产生的。用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去,或者把表中的一条记录自动封装成对象。

         

采用ORM优势在于,程序员采用面向对象的方法来访问数据库,简化了编码,提高了开发速度,ORM自动完成类和表,属性名和字段名的映射。

    使用本ORM框架,在处理查询业务逻辑时,只要编写形如"from 类名"的SQL语句,就可以得到封装好的所查询所有结果的List集合,处理添加业务时,只要调用Add(obj)方法即可实现添加功能。其他的功能读者可自行添加。

二、整体思路

  1、自定义ORM注解,包含@Table和@Column。

   2、写一个类,解析注解信息,并存入Map对象

   3、实现查询和添加功能

   4、使用自定义的ORM框架,实现业务逻辑

   5、测试

三、具体实现

  1、整体架构

     

   2、建表并插入数据的SQL

       showdatabases;

       create database czf;

       use czf;

       create table stu(id int primary key,namevarchar(40),age int);

       insert into stuvalues(1,'czf',34),(2,'afeng',25);

       select * from stu;

       createtable teacher(tid int primary key,tname varchar(40),tage int);

       insertinto teacher values(1,'czf',34),(2,'afeng',25);

       insert into teacher(tid,tname,tage)values(3,'czf3',33);

        select * from teacher;

3、具体代码

                 第一部分  ORM部分代码的编写

   3.1 Table.java

     packagecn.com.bochy.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

 * 自定义注解,用于注解类名所对应的表名

 * @authorchenzhengfeng

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface Table {

      String value();//表名

}

3.2 Column.java

   package cn.com.bochy.annotation;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

 * 自定义注解,用于注解对象的属性名所对应的表的列名

 * @authorchenzhengfeng

 */

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface Column {

   String value();//列名

}

3.3 OrmImpl.java

   package cn.com.bochy.orm;

import java.lang.reflect.Field;

import java.util.HashMap;

import java.util.Map;

import cn.com.bochy.annotation.Column;

import cn.com.bochy.annotation.Table;

/**

 * 解析注解信息,并存入Map

 * @authorchenzhengfeng

 */

public class OrmImpl {

    //用于存储类名对应的表名,其中key是类名,value是表名

    private Map<String,String>mapTable=newHashMap<String,String>();

    //用于属性名对应的表的字段名,其中key是属性名,value是字段名

    private Map<String,String>mapColumns=newHashMap<String,String>();

    public Map<String, String> getMapTable() {

       returnmapTable;

    }

    public void setMapTable(Map<String, String> mapTable) {

       this.mapTable =mapTable;

    }

    private  StringtableName="";

    public String getTableName() {

       returntableName;

    }

    public void setTableName(String tableName) {

       this.tableName =tableName;

    }

    public Map<String, String> getMapColumns() {

       returnmapColumns;

    }

    public void setMapColumns(Map<String, String> mapColumns) {

       this.mapColumns =mapColumns;

    }

    /**

     * 解析实体类的注解信息,其中c1是实体类的类对象

     * @param c1

     */

public void parseAnnotation(Class<?> c1) {

    Table table=c1.getAnnotation(Table.class);

    tableName=table.value();//获取注解的表名

    mapTable.put(c1.getName(),tableName);//存入

    Field[] fields=c1.getDeclaredFields();//获取所有的属性名

    for(Fieldf:fields) {//遍历属性名

       if(!f.getName().equals("serialVersionUID")) {

           Column c=f.getAnnotation(Column.class);

           mapColumns.put(f.getName(),c.value());//获取该属性名所对应的字段,并存入

       }

    }

}

}

3.4  OrmQuery.java

package cn.com.bochy.orm;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import cn.com.bochy.dbutil.DBHepler;

/**

 * 实现查询功能

 * @authorchenzhengfeng

 *

 */

public class OrmQuery {

    DBHepler helper=new DBHepler();

    private static OrmImpl orm=null;

    private static String tableName="";

    private static Map<String,String> mapColumns=null;//存储属性和字段对应关系的MAP

    private static Map<String,String> mapTables=null;//存储类名和表名对应关系的MAP

    private Class<?>classc1;//查询对象的类对象

    /**

     * 通过构造方法实现初始化工作

     * @param c1

     */

    public OrmQuery(Class<?>c1) {

       this.classc1=c1;

        orm=new OrmImpl();

           orm.parseAnnotation(classc1);//解析要查询对象的注解信息

           tableName=orm.getTableName();

           mapColumns=orm.getMapColumns();

           mapTables=orm.getMapTable();

    }

    /**

     * 查询sql形如"from类名"格式的语句,并封装成List,其他的形式请读者自行添加

     * @param hql

     * @return

     */

    @SuppressWarnings("rawtypes")

    public List query(Stringhql){ 

        int index=hql.indexOf("from");

        /**

         * 以下语句是从hql语句中截取类名

         */

        StringclassName="";//类名

        StringfullclassName="";//包含包名的类名

        Stringsql="";

        Stringhqlsub=hql.substring(index+5);//form的长度为4,再加上空格,所以为5

        className=hqlsub;

           //遍历mapTables,查找类名对应的表名

        for(Stringkey:mapTables.keySet()) {

           if(key.contains(className)) {

               tableName=mapTables.get(key);

               fullclassName=key;

              

           }

        }

        sql="select * from "+tableName;

     ResultSet rs= helper.query(sql, null);

    List<Object>lists=new ArrayList<Object>();

        try {

           while(rs.next()) {         

              Class<?>c1=  Class.forName(fullclassName);  //查询对象的类对象    

              Objects=    c1.newInstance();//创建一个查询对象

           Field[]fs=   c1.getDeclaredFields();//获取该对象的所有属性

             for(Fieldf:fs) {//遍历属性

               String fname= f.getName();//获取某个属性名

              StringsetMethod="set"+FirstBig(fname);//某个属性名对应的setter方法名

                   Method[] methods=c1.getDeclaredMethods();//获取该对象的所有方法

                   for(Methodm:methods) {//遍历方法

                       if(m.getName().equals(setMethod)) {//如果找到对应的方法

                          String columnName=mapColumns.get(fname);//属性名对应的字段名       

                             m.invoke(s,rs.getObject(columnName));//执行该setter方法,给对象m赋值

                          break;

                       }

                   }

             }

              lists.add(s);//把对象存入列表

           }

       } catch (SQLException |ClassNotFoundException | InstantiationException | IllegalAccessExceptione) {

           // TODO Auto-generated catch block

           e.printStackTrace();

       } catch(IllegalArgumentExceptione) {

           // TODO Auto-generatedcatch block

           e.printStackTrace();

       } catch (InvocationTargetExceptione) {

           // TODO Auto-generatedcatch block

           e.printStackTrace();

       }

      return lists;  

    }

    //把第一个字符变为大写

    public String FirstBig(Stringstr) {

        returnstr.substring(0,1).toUpperCase()+str.substring(1);

    }

}

3.5  OrmAdd.java

package cn.com.bochy.orm;

import java.lang.reflect.Field;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import cn.com.bochy.dbutil.DBHepler;

/**

 * 实现ORM中的添加功能

 * @authorchenzhengfeng

*/

public class OrmAdd {

    DBHepler helper=new DBHepler();

    private static OrmImpl orm=null;

    private static Map<String,String> mapColumns=null;

    private Class<?>classc1;//指定要添加的对象的类类型

    //通过构造方法初始化

    public OrmAdd(Class<?>c1) {

       this.classc1=c1;

        orm=new OrmImpl();

           orm.parseAnnotation(classc1);//解析注解信息

           mapColumns=orm.getMapColumns();//获取属性名和字段名的对应信息 

    }

    /**

     * 通过Java的反射机制结合注解信息实现添加功能

     * @param obj

     * @return

     */

   public boolean add(Object obj) {

       //获取表名
     for(String key:mapTables.keySet()) {
     if(key.equals(obj.getClass().getName())) {
     tableName=mapTables.get(key);
     }
     }

       Method[] methods= obj.getClass().getDeclaredMethods();//获取添加对象中所有的方法

       Field[] fileds=obj.getClass().getDeclaredFields();//获取添加对象中所有的属性

       String sqlColumn="";//用于拼接要添加表中所有的字段

       String sqlvalue="";//用于拼接要添加的所有值,用?代替

      List<Object> parmas=newArrayList<Object>();//存储要添加的所有值

       for(Fieldf:fileds)//遍历属性

       for(Methodm:methods) {//遍历方法

               //获取该属性对应的getter方法

           if(m.getName().equals("get"+FirstBig(f.getName()))) {      

               Object values1;

              try {

                  values1 = m.invoke(obj);//调用该对象的getter方法

                  parmas.add(values1);//把添加的值存入列表       

                  sqlColumn+=mapColumns.get(f.getName())+",";

                  sqlvalue+="?,";

              } catch (IllegalAccessExceptione) {

                  // TODO Auto-generatedcatch block

                  e.printStackTrace();

              } catch (IllegalArgumentExceptione) {

                  // TODO Auto-generatedcatch block

                  e.printStackTrace();

              } catch (InvocationTargetExceptione) {

                  // TODO Auto-generatedcatch block

                  e.printStackTrace();

              }          

           }

       }

       sqlColumn=CutoutLastChar(sqlColumn);//把最后一个","去掉

       sqlvalue=CutoutLastChar(sqlvalue);//把最后一个","去掉

       String sql="insert into "+tableName+"("+sqlColumn+")"+" values("+sqlvalue+")";

      Object[] param=parmas.toArray();//把集合列表转化为数组

    return helper.noQuery(sql, param); //调用helper对象中noQuery实现添加功能

   }

   /**

    * 去掉字符串最后一个字符

    * @param str

    * @return

    */

   public String CutoutLastChar(Stringstr) {

       returnstr.substring(0,str.length()-1);

   }

   /**

    * 把字符串的首字符变为大写

    * @param str

    * @return

    */

    public String FirstBig(Stringstr) {

        returnstr.substring(0,1).toUpperCase()+str.substring(1);

    }

}

3.6 DBHepler.java

package cn.com.bochy.dbutil;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

/**

 * 简单的JDBC的封装

 * @authorchenzhengfeng

 *

 */

public class DBHepler {

    private  Stringurl="jdbc:mysql://localhost:3306/czf";

    private  Stringuser="root";

    private  Stringpassword="root";

    public  Connectionconn=null;

    public  PreparedStatementpstmt=null;

    public  ResultSetrs=null;

   //1、得到连接对象

   public  ConnectiongetConnection(){

       try {

       Class.forName("com.mysql.jdbc.Driver");

       conn=DriverManager.getConnection(url,user,password);

    } catch (ClassNotFoundExceptione) {

       // TODO Auto-generatedcatch block

       e.printStackTrace();

    } catch (SQLExceptione) {

       // TODO Auto-generatedcatch block

       e.printStackTrace();

    }

    return conn

   }

   //2、关闭资源

   public  void closeAll(){

       try {

       if(rs!=null){

              rs.close();

          }

          if(pstmt!=null){

              pstmt.close();

          }

          if(conn!=null){

              conn.close();

          }

    } catch (SQLExceptione) {

       // TODO Auto-generatedcatch block

       e.printStackTrace();

      

      

    }

   }

    //3、通用查询方法

   public  ResultSetquery(Stringsql,Object[]param){

       try {

          getConnection();

       pstmt=conn.prepareStatement(sql);

       if(param!=null)

       for(inti=0;i<param.length;i++){

           pstmt.setObject(i+1,param[i]);

       }

       rs=pstmt.executeQuery();

    } catch (SQLExceptione) {

       // TODO Auto-generatedcatch block

       e.printStackTrace();

    }

      

       returnrs;

   }

   //4、通用非查询方法

   public  boolean noQuery(String sql,Object[]param){

       getConnection();

       int a=0;

       try {

       pstmt=conn.prepareStatement(sql);

       if(param!=null)

           for(inti=0;i<param.length;i++){

              pstmt.setObject(i+1,param[i]);

           }

       a=pstmt.executeUpdate();

    } catch (SQLExceptione) {

       // TODO Auto-generatedcatch block

       e.printStackTrace();

    }

       closeAll();

       if(a>0)

       return true;

       else

          return false;

   }

}

             第二部分  ORM应用

3.7  实体类Stu.java

package cn.com.bochy.entity;

import java.io.Serializable;

import cn.com.bochy.annotation.Column;

import cn.com.bochy.annotation.Table;

/**

 * 实体类

 * @author Administrator

 *

 */

@Table("stu")//通过注解,类Stu对应表stu

public class Stu implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column("id")//通过注解,属性名id对应字段名(列名)id

    private int id;

   

public int getId() {

       returnid;

    }

    public void setId(intid) {

       this.id =id;

    }

public String getName() {

       returnname;

    }

    public void setName(String name) {

       this.name =name;

    }

    public int getAge() {

       returnage;

    }

    public void setAge(intage) {

       this.age =age;

    }

    @Column("name")//通过注解,属性名name对应字段名(列名)name

private String name;

    @Column("age")//通过注解,属性名age对应字段名(列名)age

  private int age;

  public Stu() {

    // TODO Auto-generatedconstructor stub

}

}

3.8 实体类Teacher.java

package cn.com.bochy.entity;

import java.io.Serializable;

import cn.com.bochy.annotation.Column;

import cn.com.bochy.annotation.Table;

@Table("teacher")//通过注解,Teacher对应表teacher

public class Teacher implements Serializable {

    private static final long serialVersionUID = 1L;

    @Column(value="tid")//通过注解,属性名id对应字段名(列名)tid

    private int id;

   

public int getId() {

       returnid;

    }

    public void setId(intid) {

       this.id =id;

    }

public String getName() {

       returnname;

    }

    public void setName(String name) {

       this.name =name;

    }

    public int getAge() {

       returnage;

    }

    public void setAge(intage) {

       this.age =age;

    }

    @Column("tname")//通过注解,属性名name对应字段名(列名)tname

private String name;

    @Column("tage")//通过注解,属性名age对应字段名(列名)tage

  private int age;

  public Teacher() {

    // TODO Auto-generatedconstructor stub

}

}

3.9  具体业务逻辑类StuBiz.java

package cn.com.bochy.biz;

import java.util.ArrayList;

import java.util.List;

import cn.com.bochy.entity.Stu;

import cn.com.bochy.orm.OrmAdd;

import cn.com.bochy.orm.OrmQuery;

/**

 * 使用自定义ORM框架实现具体的业务逻辑

 * @authorchenzhengfeng

 */

public class StuBiz {

       OrmQuery query=new OrmQuery(Stu.class);

       OrmAdd Add=new OrmAdd(Stu.class);

     @SuppressWarnings("rawtypes")

    List lists=new ArrayList();

  @SuppressWarnings({ "rawtypes" })

  /**

   * 查选业务逻辑

   * @return

   */

public List getAllStus(){

      String hql="from Stu";

      lists=query.query(hql);

      return lists;

   }

  /**

   * 添加业务逻辑

   * @params

   * @return

   */

  public boolean add(Stu s){

      return Add.add(s);

   }

}

3.10 具体业务逻辑类TeacherBiz.java

package cn.com.bochy.biz;

import java.util.ArrayList;

import java.util.List;

import cn.com.bochy.entity.Stu;

import cn.com.bochy.entity.Teacher;

import cn.com.bochy.orm.OrmAdd;

import cn.com.bochy.orm.OrmQuery;

/**

 * 使用自定义ORM框架实现具体的业务逻辑

 * @authorchenzhengfeng

 *

 */

public class TeacherBiz {

     OrmQuery query=newOrmQuery(Teacher.class);

     OrmAdd Add=new OrmAdd(Teacher.class);

     List<Stu>  lists=new ArrayList<Stu>();

  @SuppressWarnings({ "unchecked", "rawtypes" })

  /**

   * 查选的业务逻辑

   * @return

   */

public List getAllTeachers(){

      String hql="from Teacher";

      lists=query.query(hql);

      return lists;

   }

  /**

   * 添加的业务逻辑

   * @param s

   * @return

   */

  public boolean addTeacher(Teacher t1) {

      return Add.add(t1);

  }

}

3.11 测试类TestDemo.java

package cn.com.bochy.test;

importcn.com.bochy.biz.StuBiz;

importcn.com.bochy.biz.TeacherBiz;

importcn.com.bochy.entity.Stu;

importcn.com.bochy.entity.Teacher;

public class TestDemo {

  public static void main(String[] args) {

     StuBiz biz=new StuBiz();

     Stu s1=new Stu();

      s1.setId(5);

      s1.setAge(25);

      s1.setName("dsew25");

      biz.add(s1); 

      System.out.println(biz.getAllStus().size());

      for(Object s:biz.getAllStus()) {

         if(sinstanceof Stu) {

             Stu stu=(Stu)s;

             System.out.println(stu.getId()+" "+stu.getName()+"  "+stu.getAge());

         }

      }

     

     TeacherBiz tbiz=new TeacherBiz();

      Teacher t1=new Teacher();

    t1.setId(5);

    t1.setName("sds5");

    t1.setAge(25);

   

    tbiz.addTeacher(t1);

      System.out.println(tbiz.getAllTeachers().size());

      for(Object s:tbiz.getAllTeachers()){

         if(sinstanceof Teacher) {

             Teacher t=(Teacher)s;

             System.out.println(t.getId()+" "+t.getName()+"  "+t.getAge());

         }

      }

}

}

四、推荐内容

http://blog.csdn.net/zhoudaxia/article/details/33731583 

阅读全文
0 0