你的位置:首页 > Java教程

[Java教程]将CachedRowSet中的数据转储到对象中

虽然还有很多bug,但凑合能用,就是将CachedRowSet中的数据转换成对象或List。省去了繁琐难看的一系列get/set方法。

先说调用:

注:

cachedRowSet是查询的结果集

Student是对应于Student表的实体类

1. 从数据库Student表中查询出多行数据,要将其存入ArrayList<Student>中: 

ArrayList<Student> student = Convert.RStoList(cachedRowSet , Student.class ) ;

2. 从数据库Student表中查询出单行数据,并将其存入Student对象中:

cachedRowSet.next() ;

Student student = Convert.RStoObject(cachedRowSet , Student.class) ;

 1 package util; 2  3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.sql.ResultSetMetaData; 6 import java.sql.SQLException; 7 import java.text.ParseException; 8 import java.text.SimpleDateFormat; 9 import java.util.ArrayList; 10 import java.util.Date; 11  12 import javax.sql.rowset.CachedRowSet; 13  14 import com.sun.rowset.CachedRowSetImpl; 15  16 /** 17  *  18  * @author caiyao  19  * 20  * @function 类型转换 21 */ 22 public class Convert { 23   /** 24    * 将CachedRowSetImpl中的多条记录存储进List中 25    * @param cachedRS CachedRowSetImpl结果集 26    * @param c List中元素类型 27    * @return ArrayList对象 28    * @throws SQLException cachedRS.next()导致的异常 29    * @throws RuntimeException  30    * @throws InvocationTargetException  31    * @throws ClassNotFoundException  32    * @throws NoSuchMethodException  33    * @throws IllegalAccessException  34    * @throws InstantiationException  35   */ 36   public static <T> ArrayList<T> RStoList(CachedRowSet cachedRS , Class<T> c) 37       throws SQLException, InstantiationException, IllegalAccessException,  38       NoSuchMethodException, ClassNotFoundException, InvocationTargetException,  39       RuntimeException{ 40     ArrayList<T> store = new ArrayList<T>() ; 41     while(cachedRS.next()){ 42       T object = RStoObject(cachedRS , c ) ; 43       store.add(object) ; 44     } 45     return store ; 46   } 47    48   /** 49    * 将ResultSet类型的结果集转换成Object类型的对象 50    * 注:  51    * 1. 该方法只能转换只有一条结果的CachedRowSet。  52    * 2.rs结果集中得到的值xxx,在类中要有相应的setXxx方法 53    *  54    * @param rs 55    *      结果集 56    * @param c 57    *      Class类型的值,可以通过Class.forName(类名)获取,要确定该类有无参的构造方法, 58    *      否则会出现InstantiationException异常 59    * @return 转换之后的对象 60    * @throws InstantiationException 61    * @throws IllegalAccessException 62    * @throws SQLException 63    * @throws RuntimeException 64    * @throws NoSuchMethodException 65    * @throws ClassNotFoundException 66    * @throws InvocationTargetException 67    *       注:  68    *        1. 该方法只能转换只有一条结果的CachedRowSet。  69    *        2.rs结果集中得到的值xxx,在类中要有相应的setXxx方法 70    *       3. 在单独调用这个方法的时候(不是通过RStoList的间接调用)。 71    *       需要在传递CachedRowSet这个参数之前调用rs的next()方法。否则会出现指针无效的错误 72    *       4. 使用该方法将结果集中的数据转储到对象中时,要对象中属性get/set方法要和数据库中 73    *       列名相对应。例如数据库列名为user_name,那么对象的方法就应该是setUserName/getUserName 74   */ 75   public static <T> T RStoObject(CachedRowSet rs , Class<T> c) 76       throws InstantiationException, IllegalAccessException,  77       SQLException, NoSuchMethodException, RuntimeException,  78       ClassNotFoundException, InvocationTargetException{ 79      80     // 要确定该类有无参的构造方法 81     T instance = c.newInstance() ; 82     // 获取元数据,以便得到列的信息 83     ResultSetMetaData metaData = rs.getMetaData() ; 84     // 获取列数 85     int columnNum = metaData.getColumnCount() ; 86      87     for(int i = 1 ; i <= columnNum ; i ++ ){ 88       String columnName = getColumnName(metaData.getColumnName(i)) ; 89       Class columnClassType = SQLTypeToClass(metaData.getColumnType(i)) ; 90       String columnTypeName = columnTypeToGetter(metaData.getColumnTypeName(i)) ; 91       // 反射获取对象的set方法 92       Method objectMethod = c.getMethod( 93               "set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1),  94               columnClassType 95               ) ; 96       // 反射获取CachedRowSetImpl的get方法 97       Method RSGetter = CachedRowSetImpl.class.getMethod( 98               "get"+columnTypeName.substring(0,1).toUpperCase()+columnTypeName.substring(1),  99               int.class) ;100       // 执行RS的get方法获取属性值101       Object value = RSGetter.invoke(rs,i) ;102       // 执行Object的set方法为对象赋值103       objectMethod.invoke(instance, value) ;104     }105     // 返回对象106     return instance ;107   }108   /**109    * 获取与数据库列名对应的属性名。110    * 例如:111    *     数据库列名        属性名112    *     user_name/username    userName113    * @param rawColumnName 数据库列名114    * @return 与数据库列名对应的对象属性名115   */116   public static String getColumnName(String rawColumnName ){117     if(rawColumnName.matches(".*_.*")){118       String[] words = rawColumnName.split("_") ;119       String firstWord = words[0].toLowerCase() ;120       String lastWord = words[1].substring(0, 1).toUpperCase() + words[1].substring(1).toLowerCase() ;121       String attributeName = firstWord + lastWord ;122       return attributeName ;123     }else{124       /*125        * 如果数据库列名不包含下划线,有可能只有一个单词,那么将首字母大写然后直接返回就行。126        * 如果不止一个单词那就没辙了: 怎样让第二个单词首字母大写?127        * 这里就暂时让其直接返回吧 128        * TODO : 怎样让第二个单词首字母大写129       */130       return rawColumnName.substring(0,1).toUpperCase() + rawColumnName.substring(1).toLowerCase() ;131     }132   }133   public static String columnTypeToGetter(String columnType){134     /**135      * mysql数据库中存储字符串只有varchar,但是ResultSet接口中没有定义getVarchar()方法所以将varchar转换成String即可,136     */137     if(columnType.equals("VARCHAR")){138       return "String" ;139     }140     if(columnType.equals("NVARCHAR2")){141       return "String" ;142     }143     // oracle数据库NUMBER字段类型对应Java中int144     if(columnType.equals("NUMBER")){145       return "int" ;146     }147     return columnType ;148   }149   /**150    * 将封装后的原始类型名称转换成原始类型的class151    * @param columnType 封装后的对象名称例如"java.lang.Integer" , "java.lang.Float" , "java.lang.Double"152    * @return 原始类型class类型 例如int.class float.class double.class153    * @throws ClassNotFoundException 154   */155   public static Class getColumnClassType(String columnType) throws ClassNotFoundException{156     /**157      * 数据库中的int、float、double等原始列类型当通过getColumnClassName()方法获取时,会将原始类型打包成其基础类型封装对象 158      * 例如 int --> Integer float --> Float double --> Double159      * 该方法是为了将获取的基础类型封装类名转换成原始类型的class160     */161     if(columnType.equals("java.lang.Integer")){162       return int.class ;163     }164     if(columnType.equals("java.lang.Float")){165       return float.class ;166     }167     if(columnType.equals("java.lang.Double")){168       return double.class ;169     }170     return Class.forName(columnType) ;171   }172   /**173    * 将java.sql.Types类型转化成相应的Java中对应的Class174    * @param SQLType java.sql.Types类型175    * @return Class类型的实例例如 int.class176   */177   public static Class SQLTypeToClass(int SQLType){178     switch(SQLType){179     case java.sql.Types.ARRAY : return String.class ;180     181     case java.sql.Types.BIGINT : return int.class ;182     183     case java.sql.Types.BIT : return byte.class ;184     185     case java.sql.Types.BOOLEAN : return boolean.class ;186     187     case java.sql.Types.CHAR : return char.class ;188     189     case java.sql.Types.DOUBLE : return double.class ;190     191     case java.sql.Types.FLOAT : return float.class ;192     193     case java.sql.Types.INTEGER : return int.class ;194     195     case java.sql.Types.LONGNVARCHAR : return String.class ;196     197     case java.sql.Types.LONGVARCHAR : return String.class ;198     199     case java.sql.Types.NCHAR : return String.class ;200     201     case java.sql.Types.NVARCHAR :return String.class ;202     203     case java.sql.Types.VARCHAR : return String.class ;204     // 通过rs.getDate()获取到的java.sql.Date能够直接将其赋值到java.util.Date会进行自动转换205     case java.sql.Types.DATE : return Date.class ;206     // oracle数据库的Number字段类型对应NUMERIC类型207     case java.sql.Types.NUMERIC : return int.class ;208     209     default :return String.class ;210     }211   }212   public static Date StringTodate(String dateString , String format ) throws ParseException{213     SimpleDateFormat sdf = new SimpleDateFormat(format); 214      // 将时间字符串转换成java.util.Date对象 215     Date date = sdf.parse(dateString); 216     return date ;217   }218   public static java.sql.Date utildateTosqldate(Date date){219     return new java.sql.Date(date.getTime());220   }221 }