自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Mybatis 中xml和注解映射,so easy啦

開發(fā) 前端
MyBatis 的真正強(qiáng)大在于它的語(yǔ)句映射,這是它的魔力所在。由于它的異常強(qiáng)大,映射器的 XML 文件就顯得相對(duì)簡(jiǎn)單。

[[356792]]

本文轉(zhuǎn)載自微信公眾號(hào)「Java后端技術(shù)全?!?,作者田維常。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java后端技術(shù)全棧公眾號(hào)。  

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

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

來(lái)自官網(wǎng)。

Mybatis映射九個(gè)頂級(jí)元素:

  • mapper:映射文件的根節(jié)點(diǎn),只有一個(gè)屬性namespace(命名空間),作用如下:
    • 用于區(qū)分不同的mapper,全局唯一。
    • 綁定DAO接口,即面向接口編程,當(dāng)綁定一個(gè)接口,就不用寫此接口的實(shí)現(xiàn)類,會(huì)通過(guò)接口的完全限定名找到對(duì)應(yīng)的mapper配置來(lái)執(zhí)行SQL語(yǔ)句,所以,namespace的命名必須要寫接口的完全限定名。
  • cache:配置給定命名空間的緩存。
  • cache-ref:從其他命名空間引用緩存配置。
  • resultMap:用來(lái)描述數(shù)據(jù)庫(kù)結(jié)果集和對(duì)象的對(duì)應(yīng)關(guān)系。
  • sql:可以重用的SQL塊,也可以被其他語(yǔ)句引用。通常時(shí)存放一些公用性的SQL。
  • insert:映射插入語(yǔ)句。
  • update:更新映射語(yǔ)句。
  • delete:刪除映射語(yǔ)句。
  • select:映射查詢語(yǔ)句。

xml方式

九個(gè)頂級(jí)映射元素對(duì)應(yīng)標(biāo)簽:

  1. <mapper namespace="com.tian.mybatis.mapper.UserMapper"
  2.     <resultMap id="" type=""></resultMap> 
  3.     <sql id=""></sql> 
  4.     <cache blocking="" ></cache> 
  5.     <cache-ref namespace=""></cache-ref> 
  6.     <select id="selectUserById"></select
  7.     <insert id="insert" ></insert
  8.     <update id=""></update
  9.     <delete id=""></delete
  10. </mapper> 

select詳解

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

select使用案例

  1. <?xml version="1.0" encoding="UTF-8" ?> 
  2. <!DOCTYPE mapper 
  3.         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
  4.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd"
  5. <mapper namespace="com.tian.mybatis.mapper.UserMapper"
  6.     <select id="selectUserById"  resultType="com.tian.mybatis.entity.User" parameterType="int" > 
  7.         select * from m_user where id = #{id} 
  8.     </select
  9. </mapper> 
  • id必須在這個(gè)Mapper中是唯一的,可以被用來(lái)引用這條語(yǔ)句 ,這個(gè)id必須與只對(duì)應(yīng)的是XxxMapper.java中的方法,必須是一一對(duì)應(yīng)。
  • 返回類型:User類型,resultType:查詢語(yǔ)句返回結(jié)果類型的完全限定名或別名。別名使用方式和parameterType是一樣的。
  • 參數(shù):整形,表示查詢語(yǔ)句傳入?yún)?shù)的類型和完全限定名或別名。支持基礎(chǔ)數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型。

#{參數(shù)名}:告訴MyBatis生成的PreparedStatement參數(shù),相對(duì)于JDBC中,改參數(shù)被標(biāo)識(shí)為‘?’。

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

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

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

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

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

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

UserMapper.xml

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

UserMapper.java

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

測(cè)試類:

  1. public class MybatisApplication { 
  2.     public static final String URL = "jdbc:mysql://localhost.com:3306/mblog?useUnicode=true"
  3.     public static final String USER = "root"
  4.     public static final String PASSWORD = "123456"
  5.     public static void main(String[] args) { 
  6.         String resource = "mybatis-config.xml"
  7.         InputStream inputStream = null
  8.         SqlSession sqlSession = null
  9.         try { 
  10.             inputStream = Resources.getResourceAsStream(resource); 
  11.             //工廠模式 
  12.             SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 
  13.             //獲取sql操作會(huì)話 
  14.             sqlSession = sqlSessionFactory.openSession(); 
  15.             //構(gòu)造對(duì)象(這里比較特殊,這里構(gòu)造對(duì)象的方式后面會(huì)專門分享) 
  16.             UserMapper userMapper =  sqlSession.getMapper(UserMapper.class); 
  17.             //查詢統(tǒng)計(jì) 
  18.             System.out.println(userMapper.countUser()); 
  19.         } catch (Exception e) { 
  20.             e.printStackTrace(); 
  21.         } finally { 
  22.             try { 
  23.                 inputStream.close(); 
  24.             } catch (IOException e) { 
  25.                 e.printStackTrace(); 
  26.             } 
  27.             sqlSession.close(); 
  28.         } 
  29.     } 

輸出:2

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

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

實(shí)體類User

  1. public class User { 
  2.     private Integer id; 
  3.     private String userName; 
  4.     private Integer age;  
  5.     //set get toString方法這里就不貼了 

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

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

  • type:對(duì)應(yīng)的是我們的實(shí)體類,全路徑名。
  • id:可以理解為別名。

  • id:唯一標(biāo)識(shí),此id值用于select元素resultMap屬性的引用。
  • column:對(duì)應(yīng)我們數(shù)據(jù)庫(kù)表中的字段名稱。
  • property:對(duì)應(yīng)我們的實(shí)體類的屬性,比如:User中的屬性u(píng)serName,要和數(shù)據(jù)庫(kù)表m_user中的name對(duì)應(yīng)。
  • result:標(biāo)識(shí)一些簡(jiǎn)單屬性,其中column屬性代表數(shù)據(jù)庫(kù)的字段名,property代表查詢出來(lái)的字段名映射到實(shí)體類的某個(gè)屬性。

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

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

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

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

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

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

  • resultType:直接表示返回類型, 包括基本數(shù)據(jù)類型和復(fù)雜數(shù)據(jù)類型。
  • resultMap:外部resultMap定義的引用,通過(guò)對(duì)應(yīng)的外部resultMap的id,表示結(jié)果映射到哪個(gè)resultMap上,一般用于字段名和屬性名不一致的情況,或者需要做復(fù)雜的聯(lián)合查詢以便自由控制映射結(jié)果。

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

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

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

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

增刪改案例

insert

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

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

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

  1. int insert(User user); 

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

注解方式

九個(gè)頂級(jí)映射元素對(duì)應(yīng)注解:

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

select注解

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

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

UserMapper.java添加注解

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

再次測(cè)試

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

輸出:

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

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

這么搞,再添加一個(gè)注解:

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

輸出:

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

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

insert、update、delete同樣也可以使用注解來(lái)搞定了。

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

注解和xml是否可以共存?

  1. <update id="updateAuthorIfNecessary"
  2.        update m_user 
  3.        <trim prefix="SET" suffixOverrides=","
  4.            <if test="userName != null and userName != ''"
  5.                `name` = #{userName}, 
  6.            </if> 
  7.            <if test="gender != null and gender != 0"
  8.                gender = #{gender}, 
  9.            </if> 
  10.            <if test="age != null and age != 0"
  11.                age = #{age}, 
  12.            </if> 
  13.        </trim> 
  14.        where id=#{id} 
  15.    </update

同時(shí)在UserMapper.java中的方法上添加注解

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

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

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

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

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

建議

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

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

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

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

3.可以同時(shí)使用xml和注解。

高級(jí)映射

association

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

  1. <resultMap type="com.tian.mybatis.entity.User" id="userMapRole"
  2.         <id column="id" property="id" /> 
  3.         <result column="name" property="userName" /> 
  4.         <result column="age" property="age" /> 
  5.         <association property="role" javaType="UserRole"
  6.             <id column="id" property="id" /> 
  7.             <result column="roleName" property="roleName" /> 
  8.         </association> 
  9. </resultMap> 

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

  • property:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象屬性名。
  • javaType:完整的java類名和限定名。propert所映射的屬性的類型。

子元素

  • id:一般為映射主鍵,可以提高性能。
  • result:
    • column:映射的數(shù)據(jù)庫(kù)的字段名。
    • property:映射的數(shù)據(jù)列對(duì)應(yīng)的實(shí)體對(duì)象屬性。

collection

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

  1. <resultMap type="com.tian.mybatis.entity.User" id="userMapAddress"
  2.         <id column="id" property="id"/> 
  3.         <result column="name" property="userName"/> 
  4.         <collection property="lists" ofType="UserAddress">        
  5.             <id column = "id" property = "id"
  6.             <result column="addressDesc" property="addressDesc"/> 
  7.         </collection> 
  8.     </resultMap> 

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

其余和association基本一致。

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

延遲加載:先從單表查詢,需要時(shí)再查關(guān)聯(lián)表,大大的提高了數(shù)據(jù)庫(kù)性能,因?yàn)橄鄬?duì)來(lái)說(shuō)單表查詢比多表查詢要快。

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

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

xml方式

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

注解方式

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

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

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

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

總結(jié)

本文講述了Mybatis的兩種映射方式,以及一些注意點(diǎn),一些關(guān)系和區(qū)別。

實(shí)體屬性名和數(shù)據(jù)庫(kù)表字段名不一樣的情況下,xml和注解分別是如何處理的。resultType和resultMap的區(qū)別。

 

責(zé)任編輯:武曉燕 來(lái)源: Java后端技術(shù)全棧
相關(guān)推薦

2022-11-26 00:00:02

2012-09-07 09:41:15

Win 8關(guān)機(jī)

2012-05-18 14:24:57

fedora 17安裝卸載

2019-12-19 08:56:21

MybatisSQL執(zhí)行器

2020-11-04 08:28:11

Mybatis

2019-07-17 08:41:42

Java補(bǔ)碼反碼

2023-04-03 15:04:00

RPCPHP語(yǔ)言

2018-09-05 21:07:06

數(shù)據(jù)管理

2019-03-26 11:36:28

網(wǎng)絡(luò)

2010-03-05 13:28:34

SpringObject XML

2022-07-27 08:49:34

接口加密解密

2019-12-23 10:51:40

Python車票搶票

2024-04-16 10:09:42

2021-04-23 10:38:52

Spring BootSpringMVC源碼

2022-05-06 10:42:09

JavaFlowable引擎

2014-09-18 10:27:53

U-Mail郵件系統(tǒng)郵件服務(wù)器

2020-08-12 18:11:02

戴爾

2020-04-13 14:00:07

量子計(jì)算圍棋AI

2009-06-16 13:27:59

Hibernate x

2009-09-29 15:58:22

Hibernate映射
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)