`

利用反射实现ORM

 
阅读更多

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。 

Java代码  收藏代码
  1. package com.royzhou.reflect;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.Field;  
  5. import java.lang.reflect.Method;  
  6.   
  7. public class ReflectTest {  
  8.   
  9.     private String id;  
  10.   
  11.     private String name;  
  12.   
  13.     public String property;  
  14.   
  15.     public String getId() {  
  16.         return id;  
  17.     }  
  18.   
  19.     public void setId(String id) {  
  20.         this.id = id;  
  21.     }  
  22.   
  23.     public String getName() {  
  24.         return name;  
  25.     }  
  26.   
  27.     public void setName(String name) {  
  28.         this.name = name;  
  29.     }  
  30.   
  31.     public String getProperty() {  
  32.         return property;  
  33.     }  
  34.   
  35.     public void setProperty(String property) {  
  36.         this.property = property;  
  37.     }  
  38.   
  39.     public ReflectTest() {  
  40.         System.out.println("this is a constructor with no params!!!");  
  41.     }  
  42.   
  43.     public ReflectTest(String param) {  
  44.         System.out.println("this is a constructor with  param :" + param  
  45.                 + "!!!");  
  46.     }  
  47.   
  48.     /** 
  49.      * 创建对象 
  50.      *  
  51.      * @param clazz 
  52.      * @param paramTypes:构造函数参数,如果为null表示调用无参函数 
  53.      * @return 
  54.      * @throws Exception 
  55.      */  
  56.     public Object createObject(Class clazz, Class[] paramTypes)  
  57.             throws Exception {  
  58.         Object obj = null;  
  59.         if (paramTypes == null) {  
  60.             // 无参构造函数  
  61.             obj = clazz.newInstance();  
  62.         } else {  
  63.             // 有参构造函数  
  64.             Constructor con = clazz.getConstructor(paramTypes);  
  65.             obj = con.newInstance("Test String param");  
  66.         }  
  67.         return obj;  
  68.     }  
  69.   
  70.     /** 
  71.      * 激活对象的某个方法 
  72.      *  
  73.      * @param obj 
  74.      * @param methodName 
  75.      * @throws Exception 
  76.      */  
  77.     public void invokeMethod(Object obj, String methodName) throws Exception {  
  78.         Method[] methods = obj.getClass().getDeclaredMethods(); // 拿到当前类的全部方法,包括私有的和公有的  
  79.         methods = obj.getClass().getMethods(); // 拿到当前类以及父类的所有公有方法  
  80.         for (Method m : methods) {  
  81.             if (m.getName().equals(methodName)) {  
  82.                 m.invoke(obj, new Object[] {}); // 调用方法  
  83.             }  
  84.         }  
  85.     }  
  86.   
  87.     public void getFileds(Object obj) throws Exception {  
  88.         Field[] fields = obj.getClass().getFields(); // 获取公有的属性  
  89.         fields = obj.getClass().getDeclaredFields(); // 获取公有私有属性  
  90.         for (Field f : fields) {  
  91.             System.out.println(f.getName());  
  92.         }  
  93.     }  
  94.   
  95.     public void overload(String s) {  
  96.         System.out.println("param is String :" + s);  
  97.     }  
  98.   
  99.     public void overload(int i) {  
  100.         System.out.println("param is int :" + i);  
  101.     }  
  102.   
  103.     public void testInvoke() {  
  104.         System.out.println("this is a method for invoke test!!!");  
  105.     }  
  106.       
  107.     public static void main(String[] args) throws Exception {  
  108.         ReflectTest rt = new ReflectTest();  
  109.         Object obj = rt.createObject(ReflectTest.classnull);  
  110.         System.out.println("--------------");  
  111.         obj = rt.createObject(ReflectTest.classnew Class[] { String.class });  
  112.         System.out.println("--------------");  
  113.         rt.invokeMethod(obj, "testInvoke");  
  114.         System.out.println("--------------");  
  115.         Method m = obj.getClass().getMethod("overload"int.class);  
  116.         m.invoke(obj, new Object[] { 1 });  
  117.         System.out.println("--------------");  
  118.         m = obj.getClass().getMethod("overload", String.class);  
  119.         m.invoke(obj, new Object[] { "test overload String" });  
  120.         System.out.println("--------------");  
  121.         rt.getFileds(obj);  
  122.     }  
  123. }  


利用java的反射机制可以进行简单的ORM即对象关系映射 
如下面代码: 
Java代码  收藏代码
  1. import java.lang.reflect.Method;  
  2. import java.sql.Connection;  
  3. import java.sql.PreparedStatement;  
  4. import java.sql.ResultSet;  
  5. import java.sql.ResultSetMetaData;  
  6. import java.util.ArrayList;  
  7. import java.util.List;  
  8.   
  9. public class ORMTest {  
  10.   
  11.     /** 
  12.      * @param args 
  13.      * @throws Exception 
  14.      */  
  15.     public static void main(String[] args) throws Exception {  
  16.         User user = (User) getObject(  
  17.                 "select id as Id, name as Name from user where id=1",  
  18.                 User.class);  
  19.         System.out.println(user);  
  20.     }  
  21.   
  22.     public static List<Object> getObjects(String sql, Class clazz)  
  23.             throws Exception {  
  24.         Connection conn = null;  
  25.         PreparedStatement ps = null;  
  26.         ResultSet rs = null;  
  27.         try {  
  28.             conn = JdbcUtils.getConnection();  
  29.             ps = conn.prepareStatement(sql);  
  30.             rs = ps.executeQuery();  
  31.             String[] colNames = getColNames(rs);  
  32.   
  33.             List<Object> objects = new ArrayList<Object>();  
  34.             Method[] ms = clazz.getMethods();  
  35.             while (rs.next()) {  
  36.                 Object object = clazz.newInstance(); //  
  37.                 for (int i = 0; i < colNames.length; i++) {  
  38.                     String colName = colNames[i];  
  39.                     String methodName = "set" + colName;  
  40.                     for (Method m : ms) {  
  41.                         if (methodName.equals(m.getName())) {  
  42.                             m.invoke(object, rs.getObject(colName));  
  43.                             break;  
  44.                         }  
  45.                     }  
  46.                     objects.add(object);  
  47.                 }  
  48.             }  
  49.             return objects;  
  50.         } finally {  
  51.             JdbcUtils.free(rs, ps, conn);  
  52.         }  
  53.     }  
  54.   
  55.     private static String[] getColNames(ResultSet rs) throws Exception {  
  56.         ResultSetMetaData rsmd = rs.getMetaData();  
  57.         int count = rsmd.getColumnCount();  
  58.         String[] colNames = new String[count];  
  59.         for (int i = 1; i <= count; i++) {  
  60.             colNames[i - 1] = rsmd.getColumnLabel(i);  
  61.         }  
  62.         return colNames;  
  63.     }  
  64.   
  65.     public static Object getObject(String sql, Class clazz) throws Exception {  
  66.         Connection conn = null;  
  67.         PreparedStatement ps = null;  
  68.         ResultSet rs = null;  
  69.         try {  
  70.             conn = JdbcUtils.getConnection();  
  71.             ps = conn.prepareStatement(sql);  
  72.             rs = ps.executeQuery();  
  73.             String[] colNames = getColNames(rs);  
  74.   
  75.             Object object = null;  
  76.             Method[] ms = clazz.getMethods();  
  77.             if (rs.next()) {  
  78.                 object = clazz.newInstance();  
  79.                 for (int i = 0; i < colNames.length; i++) {  
  80.                     String colName = colNames[i];  
  81.                     String methodName = "set" + colName;  
  82.                     for (Method m : ms) {  
  83.                         if (methodName.equals(m.getName())) {  
  84.                             m.invoke(object, rs.getObject(colName));  
  85.                             break;  
  86.                         }  
  87.                     }  
  88.                 }  
  89.             }  
  90.             return object;  
  91.         } finally {  
  92.             JdbcUtils.free(rs, ps, conn);  
  93.         }  
  94.     }  
  95. }  

在这个简单的ORM中,利用Java的反射机制动态创建实例,不需要事先知道要生成什么对象或对象集合,只需要在调用的时候转型(当然也可以使用jdk1.5的泛型技术),使用m.invoke(object, rs.getObject(colName))方法动态设置实例的属性,注意,在这个例子中,user类必须是一个标准的Javabean,具有各个属性的setter/getter方法以及一个没有参数的构造函数,上面例子中使用sql的别名来实现动态调用对象的方法,(Hibernate使用配置文件.hbm.xml文件完成数据库字段到javabean的映射),只需要在写查询sql的时候指定好别名就可以完成javabean属性的设置。 

假如有另外一个类 Product 
Java代码  收藏代码
  1. public class Product {  
  2.       
  3.     private String id;  
  4.       
  5.     private String name;  
  6.       
  7.     private String manufatrue;  
  8.       
  9.     public String getId() {  
  10.         return id;  
  11.     }  
  12.   
  13.     public void setId(String id) {  
  14.         this.id = id;  
  15.     }  
  16.   
  17.     public String getManufatrue() {  
  18.         return manufatrue;  
  19.     }  
  20.   
  21.     public void setManufatrue(String manufatrue) {  
  22.         this.manufatrue = manufatrue;  
  23.     }  
  24.   
  25.     public String getName() {  
  26.         return name;  
  27.     }  
  28.   
  29.     public void setName(String name) {  
  30.         this.name = name;  
  31.     }  
  32.   
  33.     public Product() {  
  34.           
  35.     }  
  36. }  

这样我们在查询的时候只需要执行下面语句就可以获得封装好的Product对象/集合 
Java代码  收藏代码
  1. Product product= (Product ) getObject("select id as Id, name as Name ,manufature as Manufature from product where id=1",Product .class);  


这样的代码更具有动态性,不用每个查询写一个查询方法 

分享到:
评论

相关推荐

    利用java反射、注解及泛型模拟ORM实现

    NULL 博文链接:https://lunzi.iteye.com/blog/1675871

    反射+注解自定义ORM

    利用Java反射和注解实现自定义的ORM,并提供相应的工具类自动生成CRUD的SQL语句,同时定义了完整的异常处理机制

    支持多数据库的ORM框架ef-orm.zip

    例如:数据库查询条件的传入问题是所有ORM框架都不能回避的一个问题,所以我经常在想——既然我们可以用向DAO传入一个Entity来实现插入操作,为什么就不能用同样的方法来描述一个不以主键为条件的update/select/...

    Liberg:用于基于 spring-boot 的 Web 开发的高性能轻量级套件

    Liberg ...利用Java的反射机制,动态地创建对象、为对象属性赋值,就可以很容易地实现将数据表中的一条记录转换为一个Java实体类的对象。可以肯定的是,几乎所有ORM(Object Relational Mapping)框架就

    asp.net知识库

    利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法 asp.net报表解决方法 SQLDMO类的使用 SQL过程自动C#封装,支持从表到基本存储过程生成 使用SQLDMO控制 SQL Server 使用SQL...

    ASP.NET中实现Form表单字段值自动填充到操作模型中

    我们知道ASP.NET MVC有个强大的地方就是Form表单提交到action的时候,可以直接将Form的参数直接装配到action的参数...我们其实可以利用反射来实例化对象的(自动装配) 好了废话不多…. pageload里面很简单了 代码如

    Spring面试题

    4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能 5.容器提供了众多的辅助类,能加快应用的开发 6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等 7.spring属于低侵入...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     21.4.1 利用数据库系统的独占锁来实现悲观锁  21.4.2 由应用程序实现悲观锁  21.5 利用Hibernate的版本控制来实现乐观锁  21.5.1 使用元素  21.5.2 使用元素  21.5.3 对游离对象进行版本检查  21.5.4 强制...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     21.4.1 利用数据库系统的独占锁来实现悲观锁  21.4.2 由应用程序实现悲观锁  21.5 利用Hibernate的版本控制来实现乐观锁  21.5.1 使用元素  21.5.2 使用元素  21.5.3 对游离对象进行版本检查  21.5.4 强制...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     21.4.1 利用数据库系统的独占锁来实现悲观锁  21.4.2 由应用程序实现悲观锁  21.5 利用Hibernate的版本控制来实现乐观锁  21.5.1 使用元素  21.5.2 使用元素  21.5.3 对游离对象进行版本检查  21.5.4 强制...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     21.4.1 利用数据库系统的独占锁来实现悲观锁  21.4.2 由应用程序实现悲观锁  21.5 利用Hibernate的版本控制来实现乐观锁  21.5.1 使用元素  21.5.2 使用元素  21.5.3 对游离对象进行版本检查  21.5.4 强制...

    拦截器和控制器的区别

    2、拦截器不依赖于servlet容器,通过动态代理实现,过滤器依赖于servlet容器 3、拦截器在方法前后,异常前后等调用,而过滤器只能在请求前和请求后各调一次。 4、拦截器可以利用依赖注入,因此在spring框架程序中,...

    springmybatis

    mybatis实战教程mybatis in action之三实现数据的增删改查 mybatis实战教程mybatis in action之四实现关联数据的查询 mybatis实战教程mybatis in action之五与spring3集成附源码 mybatis实战教程mybatis in action之...

    整理后java开发全套达内学习笔记(含练习)

    implements (关键字) 实现 ['implimәnt] import (关键字) 引入(进口,输入) Info n.信息 (information [,infә'meiʃәn] ) Inheritance [java] 继承 [in'heritәns] (遗传,遗产) initialize 预置 初始化 [i'ni...

Global site tag (gtag.js) - Google Analytics