溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

發(fā)布時間:2021-09-17 12:34:12 來源:億速云 閱讀:437 作者:chen 欄目:web開發(fā)

這篇文章主要介紹“Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)”,在日常操作中,相信很多人在Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

MyBatis 提供了XML配置和注解配置兩種方式。今天就來搞搞這兩種方式是如何實(shí)現(xiàn)的。

MyBatis 的真正強(qiáng)大在于它的語句映射,這是它的魔力所在。由于它的異常強(qiáng)大,映射器的 XML 文件就顯得相對簡單。如果拿它跟具有相同功能的JDBC  代碼進(jìn)行對比,你會立即發(fā)現(xiàn)省掉了將近 95% 的代碼。MyBatis 致力于減少使用成本,讓用戶能更專注于 SQL 代碼。

來自官網(wǎng)。

Mybatis映射九個頂級元素:

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

  • mapper:映射文件的根節(jié)點(diǎn),只有一個屬性namespace(命名空間),作用如下:

    • 用于區(qū)分不同的mapper,全局唯一。

    • 綁定DAO接口,即面向接口編程,當(dāng)綁定一個接口,就不用寫此接口的實(shí)現(xiàn)類,會通過接口的完全限定名找到對應(yīng)的mapper配置來執(zhí)行SQL語句,所以,namespace的命名必須要寫接口的完全限定名。

  • cache:配置給定命名空間的緩存。

  • cache-ref:從其他命名空間引用緩存配置。

  • resultMap:用來描述數(shù)據(jù)庫結(jié)果集和對象的對應(yīng)關(guān)系。

  • sql:可以重用的SQL塊,也可以被其他語句引用。通常時存放一些公用性的SQL。

  • insert:映射插入語句。

  • update:更新映射語句。

  • delete:刪除映射語句。

  • select:映射查詢語句。

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

xml方式

九個頂級映射元素對應(yīng)標(biāo)簽:

<mapper namespace="com.tian.mybatis.mapper.UserMapper">     <resultMap id="" type=""></resultMap>     <sql id=""></sql>     <cache blocking="" ></cache>     <cache-ref namespace=""></cache-ref>     <select id="selectUserById"></select>     <insert id="insert" ></insert>     <update id=""></update>     <delete id=""></delete> </mapper>

select詳解

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

可以看得出,后面可選項(xiàng)還是蠻多的。下面是官網(wǎng)對每項(xiàng)的解釋。

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

select使用案例

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tian.mybatis.mapper.UserMapper">     <select id="selectUserById"  resultType="com.tian.mybatis.entity.User" parameterType="int" >         select * from m_user where id = #{id}     </select> </mapper>
  • id必須在這個Mapper中是唯一的,可以被用來引用這條語句 ,這個id必須與只對應(yīng)的是XxxMapper.java中的方法,必須是一一對應(yīng)。

  • 返回類型:User類型,resultType:查詢語句返回結(jié)果類型的完全限定名或別名。別名使用方式和parameterType是一樣的。

  • 參數(shù):整形,表示查詢語句傳入?yún)?shù)的類型和完全限定名或別名。支持基礎(chǔ)數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型。

#{參數(shù)名}:告訴MyBatis生成的PreparedStatement參數(shù),相對于JDBC中,改參數(shù)被標(biāo)識為&lsquo;?&rsquo;。

別名與參數(shù)映射類型如下:

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

返回類型中別名的使用,注意:

如果是我們的entity類,那么resultType是無法使用別名的,只能使用resultMap才可以使用別名。

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tian.mybatis.mapper.UserMapper">     <resultMap id="User" type="com.tian.mybatis.entity.User"/>     <select id="selectUserById"  resultMap="User" parameterType="int" >         select * from m_user where id = #{id}     </select> </mapper>

但是如果使用的上面映射表里,也可以直接使用別名。

數(shù)據(jù)庫里有兩條數(shù)據(jù):

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tian.mybatis.mapper.UserMapper">     <select id="countUser" resultType="int">         select count(1) from m_user     </select> </mapper>

UserMapper.java

import com.tian.mybatis.entity.User; public interface UserMapper {     int countUser(); }

測試類:

public class MybatisApplication {     public static final String URL = "jdbc:mysql://localhost.com:3306/mblog?useUnicode=true";     public static final String USER = "root";     public static final String PASSWORD = "123456";     public static void main(String[] args) {         String resource = "mybatis-config.xml";         InputStream inputStream = null;         SqlSession sqlSession = null;         try {             inputStream = Resources.getResourceAsStream(resource);             //工廠模式             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);             //獲取sql操作會話             sqlSession = sqlSessionFactory.openSession();             //構(gòu)造對象(這里比較特殊,這里構(gòu)造對象的方式后面會專門分享)             UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);             //查詢統(tǒng)計(jì)             System.out.println(userMapper.countUser());         } catch (Exception e) {             e.printStackTrace();         } finally {             try {                 inputStream.close();             } catch (IOException e) {                 e.printStackTrace();             }             sqlSession.close();         }     } }

輸出:2

當(dāng)數(shù)據(jù)庫表中的字段名和我們entity中的字段名不一致,怎么處理?

在實(shí)際開發(fā)中,這種常見是在所難免。我們可以使用下面的這種方式解決。

實(shí)體類User

public class User {     private Integer id;     private String userName;     private Integer age;      //set get toString方法這里就不貼了 }

UserMapper.xml文件內(nèi)容:

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.tian.mybatis.mapper.UserMapper">     <resultMap id="User" type="com.tian.mybatis.entity.User">         <id column="id" property="id"/>         <result column="name" property="userName"/>     </resultMap>     <select id="selectUserById"  resultMap="User" parameterType="int" >         select * from m_user where id = #{id}     </select> </mapper>

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

  • type:對應(yīng)的是我們的實(shí)體類,全路徑名。

  • id:可以理解為別名。

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

  • id:唯一標(biāo)識,此id值用于select元素resultMap屬性的引用。

  • column:對應(yīng)我們數(shù)據(jù)庫表中的字段名稱。

  • property:對應(yīng)我們的實(shí)體類的屬性,比如:User中的屬性userName,要和數(shù)據(jù)庫表m_user中的name對應(yīng)。

  • result:標(biāo)識一些簡單屬性,其中column屬性代表數(shù)據(jù)庫的字段名,property代表查詢出來的字段名映射到實(shí)體類的某個屬性。

繼續(xù)使用我們前面的測試類進(jìn)行測試:

UserMapper userMapper =  sqlSession.getMapper(UserMapper.class); System.out.println(userMapper.selectUserById(1));

輸出:User{id=1, userName='tian', age=22}

注意:實(shí)體類的get set 和toString()方法這里給省略, 希望大家在使用的使用,使用快捷鍵很簡單的就搞定了。

上面提到過resultType和resultMap,那么他們兩到底有什么區(qū)別呢?

resultType和resultMap 有什么區(qū)別?

  • resultType:直接表示返回類型, 包括基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型。

  • resultMap:外部resultMap定義的引用,通過對應(yīng)的外部resultMap的id,表示結(jié)果映射到哪個resultMap上,一般用于字段名和屬性名不一致的情況,或者需要做復(fù)雜的聯(lián)合查詢以便自由控制映射結(jié)果。

兩者的關(guān)聯(lián)

當(dāng)進(jìn)行查詢時,查詢出來的每個字段都會放在一個Map里,當(dāng)查詢元素返回屬性是resultType的時候,會將鍵值對取出賦所指定的屬性。其實(shí)MyBatis的每個查詢映射的返回類型都是resultMap,只是當(dāng)我們使用resultType的時候,會自動把對應(yīng)的值賦給所指定的對象屬性,當(dāng)使用resultMap時候,因?yàn)閙ap不是很好的表示領(lǐng)域,我們就進(jìn)一步的轉(zhuǎn)化為對應(yīng)的實(shí)體對象。resultMap主要作用于復(fù)雜的聯(lián)合查詢上。

resultMap的自動映射級別:默認(rèn)級別為PARTIAL,也可以在settings更改值。

注意:resultType和resultMap本質(zhì)是一樣的,都是Map數(shù)據(jù)結(jié)構(gòu),但是二者不能同時存在。

增刪改案例

insert

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

從這里可以知道,關(guān)于增加insert是沒有返回值類型可以讓我們指定的。默認(rèn)返回int類型。

<insert id="insert" parameterType="com.tian.mybatis.entity.User">         INSERT INTO m_user(`name`,age) VALUES ( #{userName},#{age}) </insert>

對應(yīng)Mapper中的方法

int insert(User user);

另外的update和delete類似,這里就沒有必要逐一演示了。

注解方式

九個頂級映射元素對應(yīng)注解:

Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)

其他部分注解是配合九個注解進(jìn)行使用的。

select注解

把本地的UserMapper.xml刪掉,然后改一下mybatis-config.xml,把其中的UserMapper.xml給注釋掉。添加

<mapper class="com.tian.mybatis.mapper.UserMapper"/>

UserMapper.java添加注解

public interface UserMapper {     @Select("select * from m_user where id = #{id}")     User selectUserById(Integer id); }

再次測試

User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1); System.out.println(user);

輸出:

User{id=1, userName='null', age=22}

從輸出內(nèi)容看到,userName為null,這也是因?yàn)楹蛿?shù)據(jù)庫表匯中的字段name不一致導(dǎo)致的,那么如何處理呢?

這么搞,再添加一個注解:

public interface UserMapper {    @Select("select * from m_user where id = #{id}")    @Results( @Result(column = "name",property = "userName"))    User selectUserById(Integer id); }

輸出:

User{id=1, userName='tian', age=22}

這樣也就是在使用注解的時候,處理實(shí)體屬性名和數(shù)據(jù)庫表字段名不一樣的問題的辦法。

insert、update、delete同樣也可以使用注解來搞定了。

@Insert、@Update、@Delete配上相應(yīng)的SQL語句。

注解和xml是否可以共存?

<update id="updateAuthorIfNecessary">        update m_user        <trim prefix="SET" suffixOverrides=",">            <if test="userName != null and userName != ''">                `name` = #{userName},            </if>            <if test="gender != null and gender != 0">                gender = #{gender},            </if>            <if test="age != null and age != 0">                age = #{age},            </if>        </trim>        where id=#{id}    </update>

同時在UserMapper.java中的方法上添加注解

@Update("update m_user set  `name` = #{userName},gender = #{gender},age = #{age} where id=#{id}") int updateAuthorIfNecessary(User user);

再次中子星的時候回報(bào)異常的:

nested exception is java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.tian.mybatis.mapper.UserMapper.updateAuthorIfNecessary.  please check file [D:\workspace\my_code\mybatis\target\classes\mapper\UserMapper.xml] and com/tian/mybatis/mapper/UserMapper.java (best guess)

大致意思就是說,已經(jīng)存在了,即就是不能同時使用xml和注解。二者選其一。

xml可以喝注解結(jié)合使用,但是得保證同一個方法不能同時存在xml和注解。

建議

簡單的sql處理可以使用注解,復(fù)雜的sql使用xml。但是實(shí)際工作還得看你待的項(xiàng)目中有沒有對這個進(jìn)行規(guī)范化。

在項(xiàng)目中無非就三種:

1.全部必須使用xml方式。

2.全部必須使用注解方式。

3.可以同時使用xml和注解。

高級映射

association

映射到JavaBean的某個復(fù)雜的”數(shù)據(jù)類型”屬性,僅處理一對一的關(guān)聯(lián)關(guān)系。

<resultMap type="com.tian.mybatis.entity.User" id="userMapRole">         <id column="id" property="id" />         <result column="name" property="userName" />         <result column="age" property="age" />         <association property="role" javaType="UserRole">             <id column="id" property="id" />             <result column="roleName" property="roleName" />         </association> </resultMap>

association的屬性節(jié)點(diǎn):

  • property:映射數(shù)據(jù)庫列的實(shí)體對象屬性名。

  • javaType:完整的java類名和限定名。propert所映射的屬性的類型。

子元素

  • id:一般為映射主鍵,可以提高性能。

  • result:

    • column:映射的數(shù)據(jù)庫的字段名。

    • property:映射的數(shù)據(jù)列對應(yīng)的實(shí)體對象屬性。

collection

映射到JavaBean的某個復(fù)雜的”數(shù)據(jù)類型”屬性,這個屬性是一個集合列表,處理一對多的關(guān)聯(lián)關(guān)系。

<resultMap type="com.tian.mybatis.entity.User" id="userMapAddress">         <id column="id" property="id"/>         <result column="name" property="userName"/>         <collection property="lists" ofType="UserAddress">                    <id column = "id" property = "id">             <result column="addressDesc" property="addressDesc"/>         </collection>     </resultMap>

ofType:完整的Java類名和限定名。propert所映射的屬性的類型。

其余和association基本一致。

association和collection都具備延遲加載功能。

延遲加載:先從單表查詢,需要時再查關(guān)聯(lián)表,大大的提高了數(shù)據(jù)庫性能,因?yàn)橄鄬碚f單表查詢比多表查詢要快。

xml和注解的關(guān)系

上面我們已經(jīng)講了兩種方式的實(shí)現(xiàn),下面來對比一下,兩種方式的關(guān)系:

xml方式

必須有個一個XxxMapper.xml與之對應(yīng),方法名對應(yīng)xml中的id,方法入?yún)⒑头椒ǔ鰠⒍急仨殞?yīng)起來,很容易出問題。我們在開發(fā)的時候有的是可以使用代碼生成器生成,但是有的是必須自己手寫,有的公司也是要求必須手寫,所以這里需要注意。

注解方式

不需要XxxMapper.xml文件,只需要在對應(yīng)XxxMapper.java中的方法上加上注解就搞定了,但是這里是有坑的。畢竟把sql放到了我們的Java代碼里了。

優(yōu)缺點(diǎn)

xml方式: 增加了xml文件,修改麻煩,條件不確定(ifelse判斷),容易出錯,特殊轉(zhuǎn)義字符比如大于小于 。

注解方式:復(fù)雜sql不好用,搜集sql不方便,管理不方便,修改需重新編譯

到此,關(guān)于“Mybatis中xml和注解映射的方式和優(yōu)缺點(diǎn)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI