摘要:背景最近在學(xué)習(xí),在處理返回值與業(yè)務(wù)對象之間的轉(zhuǎn)換非常方便,定義,標(biāo)明互相之間的轉(zhuǎn)換關(guān)系,即可輕松完成轉(zhuǎn)換。我們會寫使用原生的來獲取返回值。
背景
最近在學(xué)習(xí)Mybatis,Mybatis在處理JDBC返回值與Java業(yè)務(wù)對象之間的轉(zhuǎn)換非常方便,定義XML,標(biāo)明互相之間的轉(zhuǎn)換關(guān)系,即可輕松完成轉(zhuǎn)換。
Mybatis是JDBC的封裝,我們先來看看如果用原生的JDBC,如何完成ResultSet和Java業(yè)務(wù)對象之間的轉(zhuǎn)換,會遇到哪些不便。
CityPO,包含三個(gè)字段 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(); //從數(shù)據(jù)庫獲取的數(shù)據(jù) ResultSetMetaData meta = resultSet.getMetaData(); //從數(shù)據(jù)庫返回的數(shù)據(jù)的元數(shù)據(jù),包含列的基本信息 int cols = meta.getColumnCount(); List對象轉(zhuǎn)換cityPOS = new ArrayList ();
我們要完成的工作就是將ResultSet轉(zhuǎn)換為cityPOS。
方案一一個(gè)比較笨的方法,就是依次判斷每個(gè)列的名字,因?yàn)殚_發(fā)者知道數(shù)據(jù)庫的哪一列對應(yīng)的是業(yè)務(wù)PO中的哪個(gè)屬性,如果列名和屬性名相等,那么調(diào)用對應(yīng)屬性的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); } }缺點(diǎn)
轉(zhuǎn)換完全和具體的業(yè)務(wù)類綁定在了一起,你如果新處理一個(gè)業(yè)務(wù)類,你得再重新寫一套差不多的代碼,而且隨著類的屬性字段的增多,你的if/else代碼會越來越多,聽起來是不是很恐怖。
在調(diào)用set方法時(shí),我們需要處理類型轉(zhuǎn)換,又是一長串的代碼。我們這個(gè)方案沒用反射,不知道set屬性的類型,只能靠人為判斷,很有可能出現(xiàn)異常。
我在cityPO.setCity_id(Long.valueOf((Integer)resultSet.getObject(i))) 就遇到了把Integer直接強(qiáng)轉(zhuǎn)Long失敗,報(bào)出了異常才改成了現(xiàn)在這樣,如果這樣的代碼出現(xiàn)在你應(yīng)用的各個(gè)角落,你慌不?
結(jié)論方案1的處理和具體的代碼綁定的比較死,依靠一堆判斷來完成賦值,那么我們想到可以利用反射來完成對屬性的賦值,這樣字段再多,也不怕啦。
方案二利用反射,通過mysql字段的名稱,直接反射找到對應(yīng)屬性的set方法,執(zhí)行調(diào)用。簡單的代碼如下所示。
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);
這段我為了測試,是直接把對應(yīng)的對象的屬性名改成了數(shù)據(jù)庫中的列名。
缺點(diǎn)因?yàn)槭峭ㄟ^數(shù)據(jù)庫的列名反射出對應(yīng)的方法,而通常我們在Java中使用的是駝峰命名,怎么處理列名到對象類名的轉(zhuǎn)換,這里應(yīng)該有一定的代碼量,當(dāng)然也可以在select的時(shí)候 as成對應(yīng)的屬性名,這樣就解決了這個(gè)問題。
我們依然需要處理類型轉(zhuǎn)換。
我們可能會多選了一些列,而這個(gè)方案會統(tǒng)統(tǒng)去找反射的方法,可能會拋出異常。
結(jié)論我覺得這應(yīng)該是框架會采取的方案。
總結(jié)直接用原生的JDBC完成數(shù)據(jù)庫到Java業(yè)務(wù)對象的轉(zhuǎn)換,肯定是非常繁瑣的,從目前來看,框架應(yīng)該也是用的方案2,只不過會比方案案強(qiáng)大的多。
從使用Mybatis這一段時(shí)間來看,其在這個(gè)方案做了這么幾件事。
解決了數(shù)據(jù)庫列名到Java列名的映射。
解決了數(shù)據(jù)庫類型到Java類型的轉(zhuǎn)換工作。
在轉(zhuǎn)換過程中具備一定的容錯(cuò)能力。
后續(xù)后續(xù)會研究下Mybatis在這方面所做的工作和源碼,有興趣可以持續(xù)關(guān)注我的微信公眾號。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67417.html
摘要:什么是呢全稱,是提出的一個(gè)對象持久化規(guī)范,各應(yīng)用服務(wù)器自主選擇具體實(shí)現(xiàn)。僅僅只是一個(gè)規(guī)范,而不是產(chǎn)品使用本身是不能做到持久化的。只要提供了持久化類與表的映射關(guān)系,框架在運(yùn)行時(shí)就能參照映射文件的信息,把對象持久化到數(shù)據(jù)庫中。 我們在進(jìn)行事務(wù)處理往往需要和數(shù)據(jù)庫進(jìn)行交互,這其中有關(guān)系型數(shù)據(jù)庫(MySql,Sql Server,Oracle)或者是非關(guān)系型數(shù)據(jù)庫(Redis,Hadhoop)...
摘要:什么是呢全稱,是提出的一個(gè)對象持久化規(guī)范,各應(yīng)用服務(wù)器自主選擇具體實(shí)現(xiàn)。僅僅只是一個(gè)規(guī)范,而不是產(chǎn)品使用本身是不能做到持久化的。只要提供了持久化類與表的映射關(guān)系,框架在運(yùn)行時(shí)就能參照映射文件的信息,把對象持久化到數(shù)據(jù)庫中。 我們在進(jìn)行事務(wù)處理往往需要和數(shù)據(jù)庫進(jìn)行交互,這其中有關(guān)系型數(shù)據(jù)庫(MySql,Sql Server,Oracle)或者是非關(guān)系型數(shù)據(jù)庫(Redis,Hadhoop)...
摘要:我們對語句做適當(dāng)改變,就完成了注入,因?yàn)槠胀ǖ牟粫ψ鋈魏翁幚恚摾袉我柡蟮纳В隽怂袛?shù)據(jù)。查詢資料后,發(fā)現(xiàn)還要開啟一個(gè)參數(shù),讓端緩存,緩存是級別的。結(jié)論是個(gè)好東西。 背景 最近因?yàn)楣ぷ髡{(diào)整的關(guān)系,都在和數(shù)據(jù)庫打交道,增加了許多和JDBC親密接觸的機(jī)會,其實(shí)我們用的是Mybatis啦。知其然,知其所以然,是我們工程師童鞋們應(yīng)該追求的事情,能夠幫助你更好的理解這個(gè)技術(shù),面對問題...
閱讀 1241·2021-11-24 09:39
閱讀 387·2019-08-30 14:12
閱讀 2600·2019-08-30 13:10
閱讀 2443·2019-08-30 12:44
閱讀 968·2019-08-29 16:31
閱讀 852·2019-08-29 13:10
閱讀 2443·2019-08-27 10:57
閱讀 3158·2019-08-26 13:57