摘要:背景最近在學習,在處理返回值與業務對象之間的轉換非常方便,定義,標明互相之間的轉換關系,即可輕松完成轉換。我們會寫使用原生的來獲取返回值。
背景
最近在學習Mybatis,Mybatis在處理JDBC返回值與Java業務對象之間的轉換非常方便,定義XML,標明互相之間的轉換關系,即可輕松完成轉換。
Mybatis是JDBC的封裝,我們先來看看如果用原生的JDBC,如何完成ResultSet和Java業務對象之間的轉換,會遇到哪些不便。
CityPO,包含三個字段 id,cityId,cityName。我們會寫使用原生的JDBC來獲取返回值。
Integer id; Long cityId; String cityName;獲取返回值
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/demo", "root", "123456"); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM SU_City limit 10"); preparedStatement.execute(); ResultSet resultSet = preparedStatement.getResultSet(); //從數據庫獲取的數據 ResultSetMetaData meta = resultSet.getMetaData(); //從數據庫返回的數據的元數據,包含列的基本信息 int cols = meta.getColumnCount(); List對象轉換cityPOS = new ArrayList ();
我們要完成的工作就是將ResultSet轉換為cityPOS。
方案一一個比較笨的方法,就是依次判斷每個列的名字,因為開發者知道數據庫的哪一列對應的是業務PO中的哪個屬性,如果列名和屬性名相等,那么調用對應屬性的set方法,如下面的代碼所示。
while (resultSet.next()) { CityPO cityPO = new CityPO(); for (int i = 1; i <= cols; i++) { if (meta.getColumnName(i).equals("id")) { cityPO.setId((Integer) resultSet.getObject(i)); } else if (meta.getColumnName(i).equals("city_id")) { cityPO.setCity_id(Long.valueOf((Integer)resultSet.getObject(i))); } else if (meta.getColumnName(i).equals("city_name")) { cityPO.setCity_name((String) resultSet.getObject(i)); } cityPOS.add(cityPO); } }缺點
轉換完全和具體的業務類綁定在了一起,你如果新處理一個業務類,你得再重新寫一套差不多的代碼,而且隨著類的屬性字段的增多,你的if/else代碼會越來越多,聽起來是不是很恐怖。
在調用set方法時,我們需要處理類型轉換,又是一長串的代碼。我們這個方案沒用反射,不知道set屬性的類型,只能靠人為判斷,很有可能出現異常。
我在cityPO.setCity_id(Long.valueOf((Integer)resultSet.getObject(i))) 就遇到了把Integer直接強轉Long失敗,報出了異常才改成了現在這樣,如果這樣的代碼出現在你應用的各個角落,你慌不?
結論方案1的處理和具體的代碼綁定的比較死,依靠一堆判斷來完成賦值,那么我們想到可以利用反射來完成對屬性的賦值,這樣字段再多,也不怕啦。
方案二利用反射,通過mysql字段的名稱,直接反射找到對應屬性的set方法,執行調用。簡單的代碼如下所示。
Class> clazz = Class.forName("po.CityPO"); Object obj = clazz.newInstance(); for (int i = 1; i <= cols; i++) { Field field = null; field = clazz.getDeclaredField(meta.getColumnName(i)); field.setAccessible(true); field.set(obj, resultSet.getObject(i)); } cityPOS.add((CityPO) obj);
這段我為了測試,是直接把對應的對象的屬性名改成了數據庫中的列名。
缺點因為是通過數據庫的列名反射出對應的方法,而通常我們在Java中使用的是駝峰命名,怎么處理列名到對象類名的轉換,這里應該有一定的代碼量,當然也可以在select的時候 as成對應的屬性名,這樣就解決了這個問題。
我們依然需要處理類型轉換。
我們可能會多選了一些列,而這個方案會統統去找反射的方法,可能會拋出異常。
結論我覺得這應該是框架會采取的方案。
總結直接用原生的JDBC完成數據庫到Java業務對象的轉換,肯定是非常繁瑣的,從目前來看,框架應該也是用的方案2,只不過會比方案案強大的多。
從使用Mybatis這一段時間來看,其在這個方案做了這么幾件事。
解決了數據庫列名到Java列名的映射。
解決了數據庫類型到Java類型的轉換工作。
在轉換過程中具備一定的容錯能力。
后續后續會研究下Mybatis在這方面所做的工作和源碼,有興趣可以持續關注我的微信公眾號。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67417.html
摘要:什么是呢全稱,是提出的一個對象持久化規范,各應用服務器自主選擇具體實現。僅僅只是一個規范,而不是產品使用本身是不能做到持久化的。只要提供了持久化類與表的映射關系,框架在運行時就能參照映射文件的信息,把對象持久化到數據庫中。 我們在進行事務處理往往需要和數據庫進行交互,這其中有關系型數據庫(MySql,Sql Server,Oracle)或者是非關系型數據庫(Redis,Hadhoop)...
摘要:什么是呢全稱,是提出的一個對象持久化規范,各應用服務器自主選擇具體實現。僅僅只是一個規范,而不是產品使用本身是不能做到持久化的。只要提供了持久化類與表的映射關系,框架在運行時就能參照映射文件的信息,把對象持久化到數據庫中。 我們在進行事務處理往往需要和數據庫進行交互,這其中有關系型數據庫(MySql,Sql Server,Oracle)或者是非關系型數據庫(Redis,Hadhoop)...
摘要:我們對語句做適當改變,就完成了注入,因為普通的不會對做任何處理,該例中單引號后的生效,拉出了所有數據。查詢資料后,發現還要開啟一個參數,讓端緩存,緩存是級別的。結論是個好東西。 背景 最近因為工作調整的關系,都在和數據庫打交道,增加了許多和JDBC親密接觸的機會,其實我們用的是Mybatis啦。知其然,知其所以然,是我們工程師童鞋們應該追求的事情,能夠幫助你更好的理解這個技術,面對問題...
閱讀 1229·2021-11-24 09:39
閱讀 380·2019-08-30 14:12
閱讀 2592·2019-08-30 13:10
閱讀 2434·2019-08-30 12:44
閱讀 959·2019-08-29 16:31
閱讀 846·2019-08-29 13:10
閱讀 2434·2019-08-27 10:57
閱讀 3152·2019-08-26 13:57