JDBC连接数据库反射实现O/R映射

[html] view plain copy
 
  1. 测试preparedStatement     
[html] view plain copy
 
  1. public void testPreparedStatement(){  
  2.     Connection connection=null;  
  3.     PreparedStatement preparedStatement=null;  
  4.     try{  
  5.         connection =JDBCTools.getConnection();  
  6.         String sql="insert into customers(name,email,birth) "+  
  7.         "values(?,?,?)";  
  8.         preparedStatement=connection.prepareStatement(sql);  
  9.         preparedStatement.setString(1, "ATGUIGU");  
  10.         preparedStatement.setString(2, "simleint@163.com");  
  11.         preparedStatement.setDate(3, new Date(new java.util.Date().getTime()));  
  12.         preparedStatement.executeUpdate();  
  13.     }catch(Exception e){  
  14.         e.printStackTrace();  
  15.     }finally{  
  16.         JDBCTools.release(null, preparedStatement, connection);  
  17.     }  
  18.    }  
[html] view plain copy
 
  1. 测试结果集元数据: 利用SQL进行查询,得到结果集。  
[html] view plain copy
 
  1. 利用反射创建实体对象,获取结果集的列的别名。  
[html] view plain copy
 
  1. 在获取结果集的每一列的值,结合3得到一个Map,键的别名,值:列的值。</span>  
[html] view plain copy
 
  1. 再利用反射为2的对应的属性赋值:属性为Map的键,值为Map的值。</span>  
 
[html] view plain copy
 
  1. public void testResultSetMetaData(){  
  2. Customer customer=null;  
  3. Connection conn=null;  
  4. PreparedStatement preparedStatement=null;  
  5. ResultSet rs=null;  
  6. try{  
  7.     String sql="select ID id,NAME name,EMAIL email,BIRTH birth from customers";  
  8.     conn=JDBCTools.getConnection();  
  9.     preparedStatement=conn.prepareStatement(sql);  
  10. 1得到rs  
  11.     rs=preparedStatement.executeQuery();  
  12.       
  13.     Map<String,Object>values=  
  14.             new HashMap<String,Object>();  
  15.     //2得到结果集ResultSetMetaData对象。  
  16.     ResultSetMetaData rsmd=rs.getMetaData();  
  17.     while(rs.next()){  
  18.     for(int i=0;i<rsmd.getColumnCount();i++){  
  19.         String columnLabel=rsmd.getColumnLabel(i+1);  
  20.         Object columnValue=rs.getObject(columnLabel);  
  21.           
  22.         values.put(columnLabel,columnValue);  
  23.     }  
  24. }  
  25.     System.out.println(values);  
  26.     Class clazz=Customer.class;  
  27.     Object object=clazz.newInstance();  
  28.     for(Map.Entry<String, Object>entry:values.entrySet()){  
  29.         String fieldName=entry.getKey();  
  30.         Object fieldValue=entry.getValue();  
  31.         System.out.println(fieldName+" :"+fieldValue);  
  32.         ReflectionUtils.setFieldValue(object,fieldName,fieldValue);  
  33.     }  
  34. }catch(Exception e){  
  35.     e.printStackTrace();  
  36. }finally{  
  37.     JDBCTools.release(rs,preparedStatement,conn);  
  38. }  
  39.   
  40. }  

抽取出泛型方法:

 

[html] view plain copy
 
  1.    public void testGet(){  
  2.     String sql="select ID id,NAME name,EMAIL email,BIRTH birth "+"From customers";  
  3.     Customer customer=get(Customer.class,sql);  
  4.     System.out.println(customer);  
  5.       
  6.    }  
  7.    public <T> T get(Class<T> clazz,String sql,Object...args){  
  8.         T entity=null;  
  9.     Connection conn=null;  
  10.     PreparedStatement preparedStatement=null;  
  11.     ResultSet rs=null;  
  12.     try{  
  13.         conn=JDBCTools.getConnection();  
  14.         preparedStatement=conn.prepareStatement(sql);  
  15.         for(int i=0;i<args.length;i++)  
  16.         {  
  17.             preparedStatement.setObject(i+1, args[i]);  
  18.         }  
  19.             //1得到rs  
  20.         rs=preparedStatement.executeQuery();  
  21.         //2得到结果集ResultSetMetaData对象。  
  22.         ResultSetMetaData rsmd=rs.getMetaData();  
  23.         //3创建一个Map<String,Object>对象,键:SQL查询的别名。值:列的值  
  24.         Map<String,Object>values=  
  25.                 new HashMap<String,Object>();  
  26.            //处理结果集。  
  27.         while(rs.next()){  
  28.         for(int i=0;i<rsmd.getColumnCount();i++){  
  29.             String columnLabel=rsmd.getColumnLabel(i+1);  
  30.             Object columnValue=rs.getObject(columnLabel);  
  31.               
  32.             values.put(columnLabel,columnValue);  
  33.         }  
  34.     }  
  35.     //5若Map不为空利用反射创建clazz对应的对象。  
  36.         if(values.size()>0){  
  37.         entity=clazz.newInstance();  
  38.         for(Map.Entry<String, Object>entry:values.entrySet()){  
  39.             String fieldName=entry.getKey();  
  40.             Object fieldValue=entry.getValue();  
  41.             ReflectionUtils.setFieldValue(entity,fieldName,fieldValue);  
  42.         }  
  43.     }  
  44.     }catch(Exception e){  
  45.         e.printStackTrace();  
  46.     }finally{  
  47.         JDBCTools.release(rs,preparedStatement,conn);  
  48.     }  
  49. return entity;  
  50.  }  

其中JDBCTools.java为:

 

 

[html] view plain copy
 
  1. /*  
  2.  * 操作JDBC的工具类,其中封装了一些工具方法  
  3.  * 通过读取配置文件从数据库服务器获取一个连接*/  
  4. public class JDBCTools {  
  5.     public static Connection getConnection() throws IOException, ClassNotFoundException, SQLException{  
  6.         //1.准备连接数据库的4个字符串。  
  7.           //1)z创建jdbc.properties对象。  
  8.         Properties properties=new Properties();  
  9.           //2)加载对应的输入流。  
  10.         InputStream in=JDBCTools.class.getClassLoader().getResourceAsStream("jdbc.properties");  
  11.         //3)加载2)对应的输入流   
  12.           properties.load(in);  
  13.         //4)具体决定user,password等4个字符串。  
  14.           String user=properties.getProperty("user");  
  15.           String password=properties.getProperty("password");  
  16.           String driver=properties.getProperty("driverClass");  
  17.           String jdbcUrl=properties.getProperty("jdbcUrl");  
  18.         //2.加载数据库驱动(对应的Driver实现类中有注册驱动的静态代码块)  
  19.           Class.forName(driver);  
  20.         //3.通过DriverManager的getConnection()方法获取数据库连接。  
  21.           return DriverManager.getConnection(jdbcUrl,user,password);  
  22.     }  
  23.     /*  
  24.      *关闭Statement,Connection */  
  25.     public static void  release(ResultSet rs,Statement statement,Connection conn){  
  26.         if(rs!=null){  
  27.             try {  
  28.                 rs.close();  
  29.             } catch (SQLException e) {  
  30.                 // TODO Auto-generated catch block  
  31.                 e.printStackTrace();  
  32.             }  
  33.         }  
  34.         if(statement!=null){  
  35.               try{  
  36.                   statement.close();  
  37.               }catch(Exception e2){  
  38.               e2.printStackTrace();  
  39.             }  
  40.           }  
  41.           if(conn!=null){  
  42.               try{  
  43.                   conn.close();  
  44.               }catch(Exception e2){  
  45.               e2.printStackTrace();  
  46.           }  
  47.         }  
  48.     }  
  49.   
  50.     public static void update(String sql) throws SQLException{        
  51.         Connection conn=null;  
  52.         Statement statement=null;  
  53.         try{  
  54.         conn=JDBCTools.getConnection();  
  55.         statement=conn.createStatement();  
  56.         statement.executeUpdate(sql);  
  57.         }catch(Exception e){  
  58.             e.printStackTrace();  
  59.         }finally{  
  60.         JDBCTools.release(null,statement, conn);  
  61.     }  
  62.    }  
  63.     public static void update(String sql,Object...args) throws IOException, ClassNotFoundException{  
  64.         Connection conn=null;  
  65.           PreparedStatement pstmt=null;  
  66.           try{  
  67.               conn=JDBCTools.getConnection();  
  68.                pstmt=conn.prepareStatement(sql);  
  69.               for(int i=0;i<args.length;i++){  
  70.                   pstmt.setObject(i+1,args[i]);  
  71.               }  
  72.               pstmt.executeUpdate();  
  73.           }catch(SQLException e){  
  74.               System.out.println("使用预编译语句更新数据操作发生异常");  
  75.           }  
  76.     }  
  77.     /*  
  78.      * 1ResultSetMetaData是描述ResultSet的元数据的对象,即从中可以获取到结果集中有多少列,列名是多少。。。  
  79.      * 2得到ResultSetNataData对象:调用ResultSet的getMetaData()方法  
  80.      * ResultSetMetaData有哪些方法。  
  81.      * int getColumnCount():SQL语句中包含哪些列。  
  82.      * String getColumnLable(int column)获取指定的列的别名,其中索引从1开始。*/  
  83.    
  84.   
  85.       
  86.        public <T> T get(Class<T> clazz,String sql,Object...args){  
  87.             /*  
  88.              * 1先利用SQL进行查询得到结果集  
  89.              * 2利用反射创建实体类的对象  
  90.              * 3获取结果集的列的别名:idcard。。。  
  91.              * 4获取结果集的每一列的值,结合3得到一个Map。键:列的别名,值:列的值  
  92.              * 5再利用反射为2的对应的属性赋值。*/  
  93.              T entity=null;  
  94.             Connection conn=null;  
  95.             PreparedStatement preparedStatement=null;  
  96.             ResultSet rs=null;  
  97.             try{  
  98.                 conn=JDBCTools.getConnection();  
  99.                 preparedStatement=conn.prepareStatement(sql);  
  100.                 for(int i=0;i<args.length;i++)  
  101.                 {  
  102.                     preparedStatement.setObject(i+1, args[i]);  
  103.                 }  
  104.                  //1得到rs  
  105.                 rs=preparedStatement.executeQuery();  
  106.                 //2得到结果集ResultSetMetaData对象。  
  107.                 ResultSetMetaData rsmd=rs.getMetaData();  
  108.                 //3创建一个Map<String,Object>对象,键:SQL查询的别名。值:列的值  
  109.                 Map<String,Object>values=  
  110.                         new HashMap<String,Object>();  
  111.                 //处理结果集。  
  112.                 while(rs.next()){  
  113.                 for(int i=0;i<rsmd.getColumnCount();i++){  
  114.                     String columnLabel=rsmd.getColumnLabel(i+1);  
  115.                     Object columnValue=rs.getObject(columnLabel);  
  116.                       
  117.                     values.put(columnLabel,columnValue);  
  118.                 }  
  119.             }  
  120.             //5若Map不为空利用反射创建clazz对应的对象。  
  121.                 if(values.size()>0){  
  122.                 entity=clazz.newInstance();  
  123.                 for(Map.Entry<String, Object>entry:values.entrySet()){  
  124.                     String fieldName=entry.getKey();  
  125.                     Object fieldValue=entry.getValue();  
  126.                     ReflectionUtils.setFieldValue(entity,fieldName,fieldValue);  
  127.                 }  
  128.             }  
  129.             }catch(Exception e){  
  130.                 e.printStackTrace();  
  131.             }finally{  
  132.                 JDBCTools.release(rs,preparedStatement,conn);  
  133.             }  
  134.         return entity;  
  135.       }   
  136.       
  137.       
  138.     public Customer getCustomer(String sql,Object...args){  
  139.         Customer customer=null;  
  140.         Connection conn=null;  
  141.         PreparedStatement preparedStatement=null;  
  142.         ResultSet rs=null;  
  143.         try{  
  144.             conn=JDBCTools.getConnection();  
  145.             preparedStatement=conn.prepareStatement(sql);  
  146.             for(int i=0;i<args.length;i++)  
  147.             {  
  148.                 preparedStatement.setObject(i+1, args[i]);  
  149.             }  
  150.             rs=preparedStatement.executeQuery();  
  151.               
  152.             if(rs.next()){  
  153.                 customer=new Customer();  
  154.                 customer.setId(rs.getInt(1));  
  155.                 customer.setName(rs.getString(2));  
  156.                 customer.setEmail(rs.getString(3));  
  157.                 customer.setBirth(rs.getDate(4));  
  158.             }  
  159.               
  160.         }catch(Exception e){  
  161.             e.printStackTrace();  
  162.         }finally{  
  163.             JDBCTools.release(rs,preparedStatement,conn);  
  164.         }  
  165.         return customer;  
  166.     }   
  167.       
  168.       
  169. }  

ReflectionUtils.java为:

 

 

[html] view plain copy
 
  1. package com.atguigu.jdbc;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6. import java.lang.reflect.Modifier;  
  7. import java.lang.reflect.ParameterizedType;  
  8. import java.lang.reflect.Type;  
  9.   
  10. /**  
  11.  * 反射的 Utils 函数集合  
  12.  * 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数  
  13.  * @author Administrator  
  14.  *  
  15.  */  
  16. public class ReflectionUtils {  
  17.   
  18.       
  19.     /**  
  20.      * 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型  
  21.      * 如: public EmployeeDao extends BaseDao<Employee, String>  
  22.      * @param clazz  
  23.      * @param index  
  24.      * @return  
  25.      */  
  26.     @SuppressWarnings("unchecked")  
  27.     public static Class getSuperClassGenricType(Class clazz, int index){  
  28.         Type genType = clazz.getGenericSuperclass();  
  29.           
  30.         if(!(genType instanceof ParameterizedType)){  
  31.             return Object.class;  
  32.         }  
  33.           
  34.         Type [] params = ((ParameterizedType)genType).getActualTypeArguments();  
  35.           
  36.         if(index >= params.length || index 0){  
  37.             return Object.class;  
  38.         }  
  39.           
  40.         if(!(params[index] instanceof Class)){  
  41.             return Object.class;  
  42.         }  
  43.           
  44.         return (Class) params[index];  
  45.     }  
  46.       
  47.     /**  
  48.      * 通过反射, 获得 Class 定义中声明的父类的泛型参数类型  
  49.      * 如: public EmployeeDao extends BaseDao<Employee, String>  
  50.      * @param <T>  
  51.      * @param clazz  
  52.      * @return  
  53.      */  
  54.     @SuppressWarnings("unchecked")  
  55.     public static<T> Class<T> getSuperGenericType(Class clazz){  
  56.         return getSuperClassGenricType(clazz, 0);  
  57.     }  
  58.       
  59.     /**  
  60.      * 循环向上转型, 获取对象的 DeclaredMethod  
  61.      * @param object  
  62.      * @param methodName  
  63.      * @param parameterTypes  
  64.      * @return  
  65.      */  
  66.     public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes){  
  67.           
  68.         for(Class<?superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){  
  69.             try {  
  70.                 //superClass.getMethod(methodName, parameterTypes);  
  71.                 return superClass.getDeclaredMethod(methodName, parameterTypes);  
  72.             } catch (NoSuchMethodException e) {  
  73.                 //Method 不在当前类定义, 继续向上转型  
  74.             }  
  75.             //..  
  76.         }  
  77.           
  78.         return null;  
  79.     }  
  80.       
  81.     /**  
  82.      * 使 filed 变为可访问  
  83.      * @param field  
  84.      */  
  85.     public static void makeAccessible(Field field){  
  86.         if(!Modifier.isPublic(field.getModifiers())){  
  87.             field.setAccessible(true);  
  88.         }  
  89.     }  
  90.       
  91.     /**  
  92.      * 循环向上转型, 获取对象的 DeclaredField  
  93.      * @param object  
  94.      * @param filedName  
  95.      * @return  
  96.      */  
  97.     public static Field getDeclaredField(Object object, String filedName){  
  98.           
  99.         for(Class<?superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){  
  100.             try {  
  101.                 return superClass.getDeclaredField(filedName);  
  102.             } catch (NoSuchFieldException e) {  
  103.                 //Field 不在当前类定义, 继续向上转型  
  104.             }  
  105.         }  
  106.         return null;  
  107.     }  
  108.       
  109.     /**  
  110.      * 直接调用对象方法, 而忽略修饰符(private, protected)  
  111.      * @param object  
  112.      * @param methodName  
  113.      * @param parameterTypes  
  114.      * @param parameters  
  115.      * @return  
  116.      * @throws InvocationTargetException   
  117.      * @throws IllegalArgumentException   
  118.      */  
  119.     public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes,  
  120.             Object [] parameters) throws InvocationTargetException{  
  121.           
  122.         Method method = getDeclaredMethod(object, methodName, parameterTypes);  
  123.           
  124.         if(method == null){  
  125.             throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");  
  126.         }  
  127.           
  128.         method.setAccessible(true);  
  129.           
  130.         try {  
  131.             return method.invoke(object, parameters);  
  132.         } catch(IllegalAccessException e) {  
  133.             System.out.println("不可能抛出的异常");  
  134.         }   
  135.           
  136.         return null;  
  137.     }  
  138.       
  139.     /**  
  140.      * 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter  
  141.      * @param object  
  142.      * @param fieldName  
  143.      * @param value  
  144.      */  
  145.     public static void setFieldValue(Object object, String fieldName, Object value){  
  146.         Field field = getDeclaredField(object, fieldName);  
  147.           
  148.         if (field == null)  
  149.             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");  
  150.           
  151.         makeAccessible(field);  
  152.           
  153.         try {  
  154.             field.set(object, value);  
  155.         } catch (IllegalAccessException e) {  
  156.             System.out.println("不可能抛出的异常");  
  157.         }  
  158.     }  
  159.       
  160.     /**  
  161.      * 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter  
  162.      * @param object  
  163.      * @param fieldName  
  164.      * @return  
  165.      */  
  166.     public static Object getFieldValue(Object object, String fieldName){  
  167.         Field field = getDeclaredField(object, fieldName);  
  168.           
  169.         if (field == null)  
  170.             throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");  
  171.           
  172.         makeAccessible(field);  
  173.           
  174.         Object result = null;  
  175.           
  176.         try {  
  177.             result = field.get(object);  
  178.         } catch (IllegalAccessException e) {  
  179.             System.out.println("不可能抛出的异常");  
  180.         }  
  181.           
  182.         return result;  
  183.     }  
  184. }  

Customer类为:

 

 

[html] view plain copy
 
  1. package com.atguigu.jdbc;  
  2.   
  3. import java.sql.Date;  
  4.   
  5. public class Customer {  
  6.      private int id;  
  7.      private String name;  
  8.      private String email;  
  9.      private Date birth;  
  10.        
  11.      public int getId() {  
  12.         return id;  
  13.     }  
  14.     public void setId(int id) {  
  15.         this.id = id;  
  16.     }  
  17.     public String getName() {  
  18.         return name;  
  19.     }  
  20.     public void setName(String name) {  
  21.         this.name = name;  
  22.     }  
  23.     public String getEmail() {  
  24.         return email;  
  25.     }  
  26.     public void setEmail(String email) {  
  27.         this.email = email;  
  28.     }  
  29.     public Date getBirth() {  
  30.         return birth;  
  31.     }  
  32.     public void setBirth(Date birth) {  
  33.         this.birth = birth;  
  34.     }  
  35.     public Customer(){}  
  36.   
  37.      public Customer(int id, String name, String email, Date birth) {  
  38.         super();  
  39.         this.id = id;  
  40.         this.name = name;  
  41.         this.email = email;  
  42.         this.birth = birth;  
  43.     }  
  44.   
  45.   
  46.     public String toString() {  
  47.         return "Customer [id=" + id + ", name=" + name + ", email=" + email  
  48.                 + ", birth=" + birth + "]";  
  49.     }  
  50.       
  51. }  
posted @ 2018-03-29 23:03  有梦就能实现  阅读(343)  评论(0编辑  收藏  举报