【MyBatis】MyBatis單表操作

MyBatis單表操作

前言

在前面一小節(jié)中,介紹了MyBatis以及MyBatis的簡單操作,并且簡單地分析了MyBatis的工作機制,接下來這一小節(jié),我們來學習MyBatis的單表操作,包括簡單的增刪改查

MyBatis單表操作

在本小節(jié)中,依然沿用上一小節(jié)所使用的環(huán)境以及資源

增加數(shù)據(jù)

CountryMapper.xml中加入下面插入代碼

<insert id="insertCountry">
    insert into 
    country(country_name, country_code)
    values (#{countryName}, #{countryCode})
</insert>

CountryMapper.java中加入代碼

int insertCountry(Country country);

測試代碼如下

@Test
public void testInsertCountry() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    CountryMapper countryMapper = sqlSession.getMapper(CountryMapper.class);

    Country country = new Country();
    country.setCountryCode("SGP");
    country.setCountryName("新加坡");

    int result = countryMapper.insertCountry(country);
    // 默認情況是不自動提交事務的,需要手動提交或者在配置文件中設(shè)置自動提交
    sqlSession.commit();
    Assert.assertEquals(1, result);
}

上面的操作基本上沒有問題,但是如果我們想插入數(shù)據(jù)的時候順便回到自增的主鍵,那還需要多做一點修改

CountryMapper.xml

<insert id="insertCountry" useGeneratedKeys="true" keyProperty="id">...</insert>

userGeneratedKyes="true"表示使用數(shù)據(jù)庫的自增主鍵,需要注意的是,只能使用一部分支持自增主鍵的數(shù)據(jù)庫如MySQL,keyProperty=""指定對應的屬性

如果是在不支持自增主鍵的數(shù)據(jù)庫,如Oracle,則需要采用下面的方式

<selectKey keyColumn = "主鍵列" resultType ="主鍵類型" keyProperty="id" order="BEFORE/AFTER">
    SELECT SQL LIKE: 
        MySQL: select LAST_INSERT_ID()
        Oracle: select SEQ_ID.nextval from dual
</selectKey>

在selectKey中,需要根據(jù)具體的數(shù)據(jù)庫來選擇對應的獲取主鍵的操作

order="before/after"需要根據(jù)具體的數(shù)據(jù)庫來選擇,有的是先生成主鍵再插入,有的是插入后再生成主鍵

上面的兩種情況中,如果主鍵列是由多個字段組成,則多個字段之間使用,分隔即可

在上面的插入情況中,我們是使用對象插入的,或者說,是使用一個參數(shù)插入的,在MyBatis中,如果是單個參數(shù),可以不同做其他操作,如果是多個參數(shù),為了在SQL中獲取參數(shù),還需要額外的一些操作,如果簡單的按照上面的操作,是無法成功的,如下

<insert id="insertCountryByNameAndCode">
        insert into country(country_name, country_code)
            values (#{countryName}, #{countryCode})
</insert>
int insertCountryByNameAndCode(String countryName, String countryCode);

執(zhí)行結(jié)果

org.apache.ibatis.exceptions.PersistenceException:
# ....
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'countryName' not found. Available parameters are [arg1, arg0, param1, param2]

可以看到,MyBatis提示我們使用arg0, arg1或者param1, param2這種方式,但實際上這種方式不太好,因為在SQL中無法看出插入的數(shù)據(jù)是哪個。有兩種解決方案,一種是將參數(shù)封裝到一個map中,key就是參數(shù)的名稱,value是參數(shù)的值,但這種方式比較麻煩,而且還需要手動構(gòu)造一個map對象,另一種方案是采用下面的方式

int insertCountryByNameAndCode(@Param("countryName") String countryName, @Param("countryCode") String countryCode);

也就是使用@Param("NAME")來指定參數(shù)的名稱,這種方式是比較推薦的,當然,這種方式本質(zhì)也是構(gòu)造一個map,只是由MyBatis來構(gòu)造,不用我們自己動手。

刪除數(shù)據(jù)

刪除數(shù)據(jù)的情況跟插入數(shù)據(jù)是類似的,只需要在CountryMapper.xml中加入對應的SQL,然后在CountryMapper.java中加入對應的操作接口即可

<delete id="deleteCountryByCountryCode">
        delete from country
        where country_code = #{countryCode}
</delete>
int deleteCountryByCountryCode(String countryCode);

測試的操作同上,這里就不展開了

修改數(shù)據(jù)

修改數(shù)據(jù)的操作也基本同上,可以通過構(gòu)造對象作為參數(shù),也可以傳入多個參數(shù),傳入多個參數(shù)則使用@Param("")指定參數(shù)名稱即可

<update id="updateCountryNameByCountryCode">
        update country
        set country_name = #{countryName}
        where country_code = #{countryCode}
</update>
int updateCountryNameByCountryCode(Country country);

測試的操作基本同上,這里就不展開了

查詢數(shù)據(jù)

查詢數(shù)據(jù)是增刪改查這幾個操作中使用頻率最高的,也是操作方式中比較豐富的一個操作,同時也是MyBatis方便性最能體現(xiàn)的一個部分,在查詢操作中,通常數(shù)據(jù)庫返回給我們的是一行行的數(shù)據(jù),在JDBC操作中,我們需要手動將一行行的數(shù)據(jù)封裝到對象中,而在MyBatis中,這些操作通常只需要指定一個resultType或者一個resultMap,MyBatis就會自動將其封裝到對象中,這在復雜操作中比較好用。

<select id="selectCountryByCountryCode">
    select id,
        country_name,
        country_code
    from country
    where country_code = #{country_code}
</select>
Country selectCountryByCountryCode(String countryCode);

當測試上面的操作時,會出現(xiàn)拋出下面的異常

Caused by: org.apache.ibatis.executor.ExecutorException: 
A query was run and no Result Maps were found for the Mapped Statement 'mapper.CountryMapper.selectCountryByCountryCode'.  
It's likely that neither a Result Type nor a Result Map was specified.

由于MyBatis從數(shù)據(jù)庫中獲取的是一行行的數(shù)據(jù),它并不知道要怎么封裝這些數(shù)據(jù),所以我們需要告訴它怎么封裝這些數(shù)據(jù),方法有兩個,一個是指定resultType,這通常適用于比較簡單的情況,另一個是resultMap,適用于比較復雜的情況

所以只需要將上面的xml修改成下面的xml即可

<select id="selectCountryByCountryCode" resultType="domain.Country">
        select id,
            country_name,
            country_code
        from country
        where country_code = #{country_code}
</select>

如果有在前面指定typeAlias,則可以直接使用類名,否則就需要使用類的全限定名

當然,上面修改后不會拋出異常,但是查詢出來的對象字段除了id之外,其他的全是null,Country{id=2, countryName='null', countryCode='null'},原因很簡單啦,就是字段沒對應上,country_namecountryName之間對不上,解決方法有兩種,一種是開啟MyBatis的下劃線轉(zhuǎn)駝峰功能

config.xml

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true" />
</settings>

這種方式適用于數(shù)據(jù)庫表字段和對象字段之間均能對應上的情況,如果對應不上,則可以使用下面的方式,通過SQL的別名方式

<select id="selectCountryByCountryCode" resultType="domain.Country">
        select id,
            country_name as CountryName,
            country_code as CountryCode
        from country
        where country_code = #{country_code}
</select>

通過上面的兩種方式之一修改之后就沒問題啦

上面我們提到,可以通過resultType來封裝結(jié)果集,也可以通過resultMap來封裝,下面介紹下resultMap的使用

<select id="selectCountryByCountryCode" resultMap="countryMap">
    select id, country_name, country_code
    from country
    where country_code = #{country_code}
</select>

<!--定義resultMap-->
<resultMap id="countryMap" type="domain.Country">
    <!--封裝屬性-->
    <id property="id" column="id" />
    <result property="countryName" column="country_name"/>
    <result property="countryCode" column="country_code"/>
</resultMap>

resultMap中有幾個需要注意的地方

  1. 盡量指定<id>,由于是將一行行的數(shù)據(jù)對應到對象中,那么就可能出現(xiàn)多行數(shù)據(jù)相同的情況,而這個時候MyBatis會將其對應到同一個對象中,如果指定了id,那么直接根據(jù)id字段的值來比較,如果沒有,則根據(jù)所有的字段來比較,比較一個字段總是比比較多個字段高效的嘛
  2. resultMap的字標簽中,均可以使用javaType=""以及jdbcType=""這兩個類型,當對象的字段跟數(shù)據(jù)庫中字段出現(xiàn)差異的時候,就需要顯式指定了,比如Date對象對應的應該是TIMESTAMP而不是數(shù)據(jù)庫中的Date,這個時候就需要指定jdbcType="TIMESTAMP"
  3. resultMap中還可以嵌套collection、association等字標簽,下一節(jié)將詳細介紹這一部分內(nèi)容

總結(jié)

在本小節(jié)中,我們主要學習了MyBatis的單表操作:增刪改查,其中需要注意的是如果傳入的時候有多個參數(shù),則推薦使用@Param("")指定參數(shù)名稱,如果需要獲取插入的數(shù)據(jù)的主鍵,可以根據(jù)數(shù)據(jù)庫來使用userGeneratedKey=""或者<selectKey>來獲取,在封裝數(shù)據(jù)集到對象的時候,可以使用resultType或者resultMap,而且必須指定一種的一種,也只能使用一種,resultType適用于比較簡單的情況,resultMap使用與比較復雜的情況,關(guān)于resultMap的更多用法我們將在下節(jié)進行詳細學習。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 6,238評論 0 4
  • MyBatis 理論篇 [TOC] 什么是MyBatis ?MyBatis是支持普通SQL查詢,存儲過程和高級映射...
    有_味閱讀 3,176評論 0 26
  • 昨天是重陽節(jié),朋友圈里各種敬老思親的圖片和文章。漂泊在外這么多年,無論走進荒無人煙的雪域高山,還是走進繁華似錦的都...
    一笑人生閱讀 514評論 0 1
  • 我是一名標準的大學生,剛剛升大二的我開始了新的規(guī)劃。從高三畢業(yè)的迷茫到大一的懶散,再到大二的奮進。人生苦短,小學...
    helen1閱讀 451評論 0 0
  • 子彈有限有所為有所不為。 有所為: 1.國外優(yōu)質(zhì)ico 仔細考察 賣一半回本 2.屯主流幣 長持 目標價 一年 3...
    WoodEast一朵閑云閱讀 171評論 0 0

友情鏈接更多精彩內(nèi)容