記自己在mybatis中設置jdbcType的一個坑


  

  項目是用ssm搭建的。主要是為app數據接口。其中有一個需求就app想要查詢一段時間內某個用戶的測量信息,所以app給我后端傳遞了3個參數,分別是appuserId(String),startDate(Date),endDate(Date)。我在controller中驗證參數沒問題之后我將參數傳遞給service層,然后在service層傳遞給dao層,執行真正的sql語句查詢。

 

service層:

1 Map<String, Object> conditionMap = new HashMap<>(3);
2 conditionMap.put("appuserId", appuserId);
3 conditionMap.put("startDate", startDate);
4 conditionMap.put("endDate", endDate);
5 
6 List<Map<String, Object>> list1 = ecgAutoAnalysisMapper.getHealthDataList(conditionMap);

  dao層:

  1 List<Map<String, Object>> getHealthDataList(Map<String, Object> conditionMap); 

   dao層的xml文件:

 1 <!--measureStartTime為測量時間,在java中是一個java.util.Date,在mysql中是TIMESTAMP類型-->
 2 <resultMap id="healthDataMap" type="map">
 3   <result property="appuserId" column="appuserId" javaType="java.lang.String" jdbcType="CHAR"/>
 4   <result property="measureStartTime" column="measureStartTime" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
 5   <result property="measureSecondLength" column="measureSecondLength" javaType="java.lang.Integer" jdbcType="INTEGER"/>
 6   <result property="hrOverallAvg" column="hrOverallAvg" javaType="java.lang.String" jdbcType="VARCHAR"/>
 7   <result property="chiefComplaint_symptom" column="chiefComplaint_symptom" javaType="java.lang.String" jdbcType="VARCHAR"/>
 8   <result property="chiefComplaint_diet" column="chiefComplaint_diet" javaType="java.lang.String" jdbcType="VARCHAR"/>
 9   <result property="chiefComplaint_activity" column="chiefComplaint_activity" javaType="java.lang.String" jdbcType="VARCHAR"/>
10 </resultMap>
11 
12 <select id="getHealthDataList" parameterType="map" resultMap="healthDataMap">
13   select
14       ea.appuserId,ea.measureStartTime,ed.measureSecondLength,ea.hrOverallAvg,ea.chiefComplaint_symptom,
15       ea.chiefComplaint_diet,ea.chiefComplaint_activity
16   from
17       ecg_auto_analysis ea
18   left join
19       ecg_data ed
20   on
21       ed.autoAnalysisId = ea.id
22   <where>
23     <if test="appuserId != null and appuserId != ''">
24       and ea.appuserId = #{appuserId,jdbcType=CHAR}
25     </if>
26     <if test="startDate != null and startDate != ''">
27       and ea.measureStartTime > #{startDate,jdbcType=Date}
28     </if>
29     <if test="endDate != null and endDate != ''">
30       and #{endDate,jdbcType=Date} > ea.measureStartTime
31     </if>
32   </where>
33 </select>

 

  結果是查詢出來的的結果與實際的不一樣。比如app傳遞參數,appuserId是“393967382ec34f53a53a4d49271a422a”,startDate是“2018-03-09 00:00:00”,endDate是“2018-03-15 23:59:59”,在數據庫中這個用戶在這段時間的測量記錄有7條,而在mybatis中查詢出來的只有4條。很明顯是mybatis的sql語句寫錯了。

數據庫查詢語句及結果(可以看到測量時間集中在兩天,一個是3月9號,一個是3月15號):

 1 select
 2     ea.appuserId,ea.measureStartTime,ed.measureSecondLength,ea.hrOverallAvg,ea.chiefComplaint_symptom,ea.chiefComplaint_diet,ea.chiefComplaint_activity
 3 from
 4     ecg_auto_analysis ea
 5 left join
 6     ecg_data ed
 7 on
 8     ed.autoAnalysisId = ea.id
 9 where
10     ea.appuserId = "393967382ec34f53a53a4d49271a422a"
11     and ea.measureStartTime > "2018-03-09 00:00:00"
12     and "2018-03-15 23:59:59" > ea.measureStartTime

 

  我是這樣解決的,當然故事很曲折,也很折磨人:

  1)先注釋掉最后的兩個if語句,mybatis的查詢結果為7,證明問題就出在最后兩個if語句中;

  2)通過翻閱以前的代碼,我把這兩個if語句中的 jdbcType=Date 去掉,查詢結果為7,然后加上  jdbcType=Date 查詢結果又為4。沒錯,問題就出在這句話上,為啥不加就好了,加上就不對了;

  3)網上查詢資料,對jdbcType這個參數的描述不多,作用不清楚,大概的意思是“jdbcType這個參數的應用場景就是,當執行mapping文件的時候,有個映射的參數為空,那么無法確定他的類型,這個時候就需要jdbcType來確定類型“。可我還是不清除啥原因導致我的查詢結果不正確;

  4)最后看了好長時間,我把 jdbcType=Date 改為 jdbcType=TIMESTAMP,查詢結果正確了(這一步花了太多時間)。

 

  我猜想原因是這樣的,當我不設置jdbcType時,最后兩個if語句在執行比較時,會把參數轉換為正確的日期類型,就是 “年月日+時分秒”這種。當我設置 jdbcType=Date 時,就指定日期只用”年月日,所以傳遞進來的startDate與endDate就變為“2018-03-09 ”,“2018-03-15”,那在此時間段的記錄當然只有4條了。但是設置 jdbcType=TIMESTAMP 時,傳遞進來啥就是啥,所以符合記錄的只有7條了,原因就是這樣。最后看看mysql數據庫中datetime、date、timestamp三種數據類型的區別吧:

 


    1) DATETIME

顯示格式:YYYY-MM-DD HH:MM:SS
時間范圍:[ '1000-01-01 00:00:00'到'9999-12-31 23:59:59']

2) DATE

顯示格式:YYYY-MM-DD
時間范圍:['1000-01-01'到'9999-12-31']

3) TIMESTAMP

顯示格式:YYYY-MM-DD HH:MM:SS
時間范圍:[ '1970-01-01 00:00:00'到'2037-12-31 23:59:59']

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM