BeanUtils工具是一種方便咱們對JavaBean進行操做的工具,是Apache組織下的產品。java
1)beanUtils 能夠便於對javaBean的屬性進行賦值。sql
2)beanUtils 能夠便於對javaBean的對象進行賦值。數據庫
3)beanUtils能夠將一個MAP集合的數據拷貝到一個javabean對象中。數組
使用beanUtils按照如下步驟~工具
前提:約定前提: 參數名稱 須要和javabean的屬性名稱保持一致!!!!spa
步驟一code
導包:導入commons-beanutils-1.8.3 包對象
與 commons-logging-1.1.3 包blog
步驟二資源
寫代碼使用~下面就來演示下常見的用法
@Test public void test1() throws Exception { //先演示一下不用工具時的作法 //1.生成對象 Student s = new Student(); /*2.經過set方法賦值 s.setId(1); s.setName("VN"); s.setAge(19); s.setClassID(5); s.setBirthday(new Date()); 用以上這種方法來給對象的屬性賦值實在是太麻煩了,下面咱們用BeanUtils來進行賦值 */ //1.獲得javaBean的一個字節碼對象 Class clazz = Class.forName("com.vmaxtam.beanutiltest.Student"); //2.生成該字節碼的一個對象 Object obj = clazz.newInstance(); //4.註冊一個日期格式轉換器 ConvertUtils.register(new DateLocaleConverter(), java.util.Date.class); //3.使用工具對該對象進行賦值 //注意: 對於基本數據類型,beanutils工具進行自動類型轉換。把String自動轉成Integer,Double,Float BeanUtils.setProperty(obj, "id", "1"); BeanUtils.setProperty(obj, "name", "VN"); BeanUtils.setProperty(obj, "age", "19"); BeanUtils.setProperty(obj, "classID", "5"); //若是要使用特殊的日期類型,則String->Date 不能自動轉換,這時候就要註冊一個轉換器 BeanUtils.setProperty(obj, "birthday", "1996-06-06"); System.out.println(obj); }
對比一下,咱們發現,使用BeanUtils裏賦值好像更麻煩。。。但這只是在這段代碼中而已,運用BeanUtils上面代碼的這個功能,
咱們能夠寫出一個通用的方法,能夠把請求中的參數拷貝到javaBean對象中!
約定前提: 請求中的參數名稱 須要和javabean的屬性名稱保持一致!!!! public static <T>T requestToBean(HttpServletRequest request , Class<T> clazz) { //建立javaBean對象 Object obj=null; try { obj=clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } //獲得請求中的每一個參數 Enumeration<String> enu = request.getParameterNames(); while(enu.hasMoreElements()) { //得到參數名 String name = enu.nextElement(); //得到參數值 String value = request.getParameter(name); //而後把參數拷貝到javaBean對象中 try { BeanUtils.setProperty(obj, name, value); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } return (T)obj; }
上面這個方法是一個泛型方法,傳不一樣的javaBean進去均可以從request中獲取參數值。在一個工程較大的項目中,若是使用這個通用的方法,就能節省不少代碼。
@Test public void test2() throws Exception { //1.生成對象 Student s1 = new Student(); Student s2 = new Student(); //2.經過set方法賦值 s1.setId(1); s1.setName("VN"); //s1.setAge(19);//基本數據類型能夠爲null,null也能拷貝 s1.setClassID(5); s1.setBirthday(new Date());//特殊類型不能爲null //需求:把s1的屬性值拷貝到S2中,注意參數的順序 BeanUtils.copyProperties(s2, s1); System.out.println(s1); System.out.println(s2); }
一句代碼就完成拷貝了,不用像之前那樣先用get()方法把s1的屬性值拿出來,再用set()方法供給s2屬性賦值
@Test public void test3() throws Exception { //1.生成對象 Map<String,Object> map = new HashMap<String,Object>(); //2.給一些參數 map.put("id", 2); map.put("name", "EZ"); map.put("age", 22); map.put("classID", 3); map.put("birthday", new Date()); //需求:把map的屬性值拷貝到S中 Student s = new Student(); BeanUtils.copyProperties(s, map); System.out.println(s); }
上面這個也是一步到位,也是使用copyProperties()這個方法來完成,這樣減小了咱們不少的操做了,十分簡便。
下面介紹一個新的概念,學會這個東西后,它可以和beanUtils組合寫出更多的通用代碼!方便咱們的項目!
數據庫中的元數據有三種:
1)數據庫元數據(DatabaseMetaData):能夠從connection對象中獲取。
這些元數據的信息包括:當前使用什麼數據庫,數據庫的版本,數據庫驅動的版本
2)參數元數據(ParameterMetaData):能夠從PreparedStatement中獲取,指sql語句中的參數
元數據的信息:參數的個數,以及每一個參數的類型
3)結果集元數據(ResultSetMetaData):能夠從ResultSet對象中獲取
元數據信息:結果集的列數,以及每列的名稱
下面就來顯示下怎麼獲取這些信息吧~
@Test public void Test1() { //獲取鏈接池 ComboPooledDataSource pool = new ComboPooledDataSource(); try { //獲取鏈接 Connection conn = pool.getConnection(); //獲取數據庫元數據 DatabaseMetaData md = conn.getMetaData(); //得到數據庫的主版本和副版本 int mj = md.getDatabaseMajorVersion(); int mi =md.getDatabaseMinorVersion(); System.out.println(mj + "."+ mi); //得到驅動版本 int dmj = md.getDriverMajorVersion(); int dmi = md.getDriverMinorVersion(); System.out.println(dmj + "."+dmi); //當前使用什麼數據庫 String b =md.getDatabaseProductName(); System.out.println(b); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
這個和beanutils沒什麼關係,因此不是重點。
PreparedStatement sta=null; Connection conn=null; @Test public void Test2() { //獲取鏈接池 ComboPooledDataSource pool = new ComboPooledDataSource(); try { //獲取鏈接 conn = pool.getConnection(); //準備SQL語句 String sql ="insert into student(sid,sname) values(?,?)"; //得到Statement sta = conn.prepareStatement(sql); //獲取元數據 ParameterMetaData md = sta.getParameterMetaData(); //獲取參數的一些信息:參數的個數 int count = md.getParameterCount(); //而後利用這個數來給參數賦值 //方便參數賦值 Object value[] = new Object[]{17,"VN"}; for(int i = 0;i<count ;i++) { sta.setObject(i+1, value[i]); } //執行 sta.executeUpdate(); //有可能具體數據庫廠商不支持下面方法 //System.out.println("第一個參數的類型:"+md.getParameterTypeName(1)); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //關閉資源 if(sta!=null){ try { sta.close(); } catch (SQLException e) { e.printStackTrace(); }if(conn!=null) { try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
以上就是使用元數據來對預編譯的SQL語句來進行方便的參數賦值的方法~當參數比較多的時候,咱們就沒必要一個一個地本身賦值,能夠利用循環來給它賦值。
咱們先發送一個查詢語句得到一個結果集,而後能夠利用元數據來很方便地封裝結果集返回的結果~
@Test public void Test3() { try { //獲取鏈接池 ComboPooledDataSource pool = new ComboPooledDataSource(); //獲取鏈接 conn = pool.getConnection(); //準備SQL語句 String sql="select * from student"; //得到statement對象 sta = conn.prepareStatement(sql); //執行,返回結果集 ResultSet res = sta.executeQuery(); //獲取結果集的元素據 ResultSetMetaData rd = res.getMetaData(); //利用元數據來封裝對象 List<Students> list = new ArrayList<Students>(); //得到結果集的列數 int colcount = rd.getColumnCount(); //循環結果集來封裝對象 while(res.next()) { Students s = new Students(); for(int i = 1; i <= colcount ; i++) { //獲得列名 String colname = rd.getColumnName(i); //獲得列值 Object value = res.getObject(colname); //利用BeanUtils,放入對象中 BeanUtils.setProperty(s, colname, value); } //把封裝好的對象放入集合 list.add(s); } //而後能夠對List其餘操做~ } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } //關閉資源 }
這就是利用元數據和BeanUtil結合方便咱們封裝結果集數據的一個例子了~利用這個特色,咱們能夠寫出更多的通用的方法。
參數說明:
sql:要預編譯的查詢語句
values:把sql語句的參數放到這個數組中
clazz:最後集合中返回的javaBean的類型
public static <T> List<T> query(String sql,Object[] values,Class<T> clazz) { Connection conn = null; PreparedStatement sta = null; ResultSet res = null; try { //獲取鏈接池 ComboPooledDataSource pool = new ComboPooledDataSource(); //獲取鏈接 conn = pool.getConnection(); //獲取statement對象,預編譯 sta = conn.prepareStatement(sql); //利用參數的元數據給預編譯的SQL語句賦值 ParameterMetaData pmd = sta.getParameterMetaData(); //得到參數個數 int pcount = pmd.getParameterCount(); //賦值 if(values != null) { for(int i=1 ;i<=pcount;i++) { sta.setObject(i, values[i-1]); } } //執行 res = sta.executeQuery(); //得到結果集元數據 ResultSetMetaData rsmd = res.getMetaData(); //建立存儲對象的集合 List<T> list = new ArrayList<T>(); //獲取列的數量 int colcount = rsmd.getColumnCount(); //封裝對象 while(res.next()) { //生成要封裝的對象的實例 Object obj = clazz.newInstance(); for(int i=1;i<=colcount;i++) { //得到列名 String colname = rsmd.getColumnName(i); //得到列值 Object colvalue = res.getObject(i); //封裝 BeanUtils.setProperty(obj, colname, colvalue); } //把封裝好的對象放入集合 list.add((T) obj); } return (List<T>)list; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); }finally{ //釋放資源 if(res!=null){ try { res.close(); } catch (SQLException e1) { e1.printStackTrace(); }} if(sta!=null){ try { sta.close(); } catch (SQLException e) { e.printStackTrace(); }} if(conn!=null){ try { conn.close();//放回鏈接池 } catch (SQLException e) { e.printStackTrace(); }} } }
以上就是一個通用的查詢方法啦~下面來看一個通用的更新方法,比上面的簡單~
public static void update(String sql,Object[] values) { Connection conn =null; PreparedStatement sta = null; try { //獲取鏈接池 ComboPooledDataSource pool = new ComboPooledDataSource(); //獲取鏈接 conn = pool.getConnection(); //預編譯 sta= conn.prepareStatement(sql); //獲取參數的元數據 ParameterMetaData pmt = sta.getParameterMetaData(); //獲取參數的個數 int pcount = pmt.getParameterCount(); //參數賦值 for(int i = 1; i<=pcount;i++) { sta.setObject(i, values[i-1]); } //執行更新 sta.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
這就完成了~
優勢:比較通用
缺點:就是每次調用這兩個方法都要在內部生產一個鏈接池,這樣一個鏈接池來完成一條語句是十分浪費的,因此這一點能夠改進~改進方法也比較簡單~這裏就不演示了~