天天看點

mysql執行SQL語句能查詢出來結果,mybatis查不出來

一.問題描述

在做自動化測試斷言驗證時,更新完使用者資訊後,拿着這個updateUserCase資訊去資料庫user表查詢,如果傳回不為空說明更新成功。

但是測試時發現斷言執行失敗

10:35:06.645 [main] DEBUG com.course.model.getUpdateUserInfo - ==>  Preparing: select * from user where id=? and username=? and sex=? and age=? 
10:35:06.646 [main] DEBUG com.course.model.getUpdateUserInfo - ==> Parameters: 12(Integer), 小蘭1(String), 1(String), 1(String)
10:35:06.647 [main] DEBUG com.course.model.getUpdateUserInfo - <==      Total: 0
user is:null



java.lang.AssertionError: expected object to not be null

	at org.testng.Assert.fail(Assert.java:94)
	at org.testng.Assert.assertNotNull(Assert.java:423)
	at org.testng.Assert.assertNotNull(Assert.java:408)
	at com.course.cases.UpdateUserInfoTest.updateUserInfo(UpdateUserInfoTest.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
	at org.testng.TestRunner.privateRun(TestRunner.java:756)
	at org.testng.TestRunner.run(TestRunner.java:610)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
	at org.testng.SuiteRunner.run(SuiteRunner.java:289)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
	at org.testng.TestNG.runSuites(TestNG.java:1133)
	at org.testng.TestNG.run(TestNG.java:1104)
	at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
	at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:110)


           

二.問題解決

1.拿着這個SQL語句去sqlyog查詢發現是能查詢出結果的;

mysql執行SQL語句能查詢出來結果,mybatis查不出來

2.嘗試在配置檔案修改編碼為utf-8

<!-- 2.資料庫連接配接位址 -->
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/java_auto_test?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                <!-- 資料庫使用者... -->
           

再次運作仍然是失敗的;

3.在網上看到

用字段拼接的方式,把#号改成
用#是走了預編譯,你傳過去的對于資料庫來說都是參數值還不是字段,你這個需要拼接sql,是以用$,底層就是jdbc的statement

           

嘗試将下面查詢語句對應的#都改成$(會有SQL注入的風險,還是更建議用#)

mysql執行SQL語句能查詢出來結果,mybatis查不出來

再次運作發現還是失敗。

4.想到檢查pom檔案,

<!--        5.mybatis依賴-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>

  <!--        8.springboot依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

    </dependencies>
           

懷疑是不是我的mybatis-spring-boot-starter版本太低了,

嘗試修改版本為2.1.0,

再次運作發現還是失敗

5.偶然發現第一次運作測試代碼斷言會執行失敗,第二次及以後就會成功了,也是很神奇,但是一直沒找到原因

6.修改測試代碼,傳入userId,不傳updateUserCase對象了;

mysql執行SQL語句能查詢出來結果,mybatis查不出來
mysql執行SQL語句能查詢出來結果,mybatis查不出來

再次運作發現斷言執行成功了

11:10:40.206 [main] INFO com.course.cases.UpdateUserInfoTest - 請求http:localhost/v1/updateUserInfo的結果是------>1
11:10:40.206 [main] DEBUG com.course.model.getUpdateUserInfo - ==>  Preparing: select * from user where id=? 
11:10:40.206 [main] DEBUG com.course.model.getUpdateUserInfo - ==> Parameters: 12(Integer)
11:10:40.207 [main] DEBUG com.course.model.getUpdateUserInfo - <==      Total: 1
user is:User(id=12, userName=小蘭3, password=111, age=13, sex=1, permission=1, isDelete=0)
db is:User(id=12, userName=小蘭3, password=111, age=13, sex=1, permission=1, isDelete=0)
11:10:40.207 [main] INFO com.course.cases.UpdateUserInfoTest - ********updateUserInfo api 驗證通過*********
           

但是結果不太對…顯示的是修改之前的結果,這也就解釋了為什麼前面根據修改之後的結果去查詢user得到的是空;

7.在服務端增加log發現服務端能查詢出正确的更新後的結果

2021-06-11 11:22:55.417 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 調用SQL更新使用者資訊成功
2021-06-11 11:22:55.417 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 調用SQL更新的使用者是:12
2021-06-11 11:22:55.418 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 更新後查到的user是:User(i
d=12, userName=小蘭6, password=111, age=16, sex=1, permission=14, isDelete=0)


           

但是對測試代碼debug發現還是舊值

mysql執行SQL語句能查詢出來結果,mybatis查不出來

8.檢查代碼發現我的sqlSession定義在TestConfig裡且為靜态的,而且被所有的測試方法公用;

SQLSession本身不是線程安全的,共用一個SQLsession的話,導緻了事務問題

每個線程都應該有它自己的SqlSession執行個體。SqlSession的執行個體不能共享使用,它也是線程不安全的。是以最佳的範圍是請求或方法範圍。絕對不能将SqlSession執行個體的引用放在一個類的靜态字段或執行個體字段中。

打開一個 SqlSession;使用完畢就要關閉它。通常把這個關閉操作放到 finally 塊中以確定每次都能執行關閉。
如下:
    SqlSession session = sqlSessionFactory.openSession();
    try {
          // do work
    } finally {
          session.close();
    }

           

修改為:在每次執行查詢的時候建立一個SQLsession

User resFromDatabase = MybatisUtils.openSession().selectOne(updateCase.getExpected(),userId);


           

9.再次運作,測試代碼已能獲得最新的記錄資訊

mysql執行SQL語句能查詢出來結果,mybatis查不出來
2021-06-11 11:33:35.345 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 調用SQL更新使用者資訊成功
2021-06-11 11:33:35.345 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 調用SQL更新的使用者是:12
2021-06-11 11:33:35.346 [http-nio-8080-exec-9] INFO  com.course.controller.UserManger - 更新後查到的user是:User(i
d=12, userName=小蘭8, password=111, age=18, sex=1, permission=14, isDelete=0)


           

10.再把測試代碼改回用updateCase查詢,更新後的記錄;

User resFromDatabase = MybatisUtils.openSession().selectOne(updateCase.getExpected(),updateCase);


           
<!--    擷取更新/删除後的使用者資訊-->
    <select id="getUpdateUserInfo" parameterType="com.course.model.UpdateUserInfoCase" resultMap="UserMap">
        select * from user
        <trim prefix="where" prefixOverrides="and">
            <if test="userId!=null and userId!=''">
                and id=#{userId}
            </if>
            <if test="userName!=null and userName!=''">
                and username=#{userName}
            </if>
            <if test="sex!=null and sex!=''">
                and sex=#{sex}
            </if>
            <if test="age!=null and age!=''">
                and age=#{age}
            </if>
            <if test="permission!=null and permission!=''">
                and permission=#{permission}
            </if>
            <if test="isDelete!=null and isDelete!=''">
                and is_delete=#{isDelete}
            </if>
        </trim>
    </select>
           

再次運作測試代碼,終于成功了

mysql執行SQL語句能查詢出來結果,mybatis查不出來

繼續閱讀