1. 程式人生 > >如何快速上手SQL對映檔案的編寫

如何快速上手SQL對映檔案的編寫

在講之前先說說它的好處:Mybatis真正強大之處就是在於SQL對映語句,也是他的魅力所在。相對於它強大的功能,SQL對映檔案的配置卻非常簡單。簡單的對比一下SQL對映配置和JDBC程式碼,發現使用SQL對映檔案配置可減少50%以上的程式碼量。並且MyBatis專注於SQL,對於開發人員來說,也可極大限度地進行SQL調優,以保證效能。

關於SQL對映檔案的幾個頂級元素配置:

頂級元素配置
mapper:對映檔案的根元素節點,只有一個屬性namespace(名稱空間),作用如下:

  • 用於區分不同的mapper,全域性唯一
  • 繫結DAO介面,即面向介面程式設計。當namespace繫結某一介面之後,可以不用寫該介面的實現類, MyBatis會通過介面的完全限定名查詢到對應的mapper配置來執行SQL語句,因此namespace的命名必須要跟介面同名

cache:配置給定名稱空間的快取
cache-ref:從其他名稱空間引用快取配置
resultMap:用來描述資料庫結果集和物件的對應關係
sql:可以重用的SQL塊,也可以被其他語句引用
insert:對映插入語句
update:對映更新語句
delete:對映刪除語句
select:對映查詢語句

使用select完成單條件查詢編寫Mapper對映檔案
<!--根據使用者名稱查詢使用者列表(模糊查詢)-->
<select id="getUserListByUserName" resultType="User" parameterType="string">
    SELECT * FROM USER WHERE userName LIKE concat('%',#{userName},'%')
</select>

各屬性介紹:
id:名稱空間中唯一的識別符號,可以被用來引用這條語句
parameterType:表示查詢語句傳入引數的型別的完全限定名或別名。
resultType:查詢語句返回結果型別的完全限定名或別名別名表

別名 對映的型別 別名 對映型別
string String double Double
byte Byte float Float
loang Long boolean Boolean
short Short date Date
int Integer map Map
integer Integer hashmap HashMap
arrayList ArrayList list List

使用select實現多條件查詢

使用物件入參
編寫對映檔案

<select id="getUserListByUser" resultType="User" parameterType="User">
    SELECT * FROM USER WHERE userName LIKE concat('%',#{userName},'%')     and userRole=#{userRole}
</select>

編寫介面

List<User> getUserListByUser(User user);

編寫測試

SqlSession sqlSession=null;
List<User> userList=new ArrayList<User>(); try{
    sqlSession=MyBatisUtil.createSqlSession();
    User user=new User();
    user.setUserName("趙");
    user.setUserRole(3);
    userList=sqlSession.getMapper(UserMapper.class).getUserListByUser(user);
}catch (Exception ex){
    ex.printStackTrace();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:
        userList) {
    System.out.println(user.getUserName()+"\t"+user.getUserRole());
}

使用Map入參編寫介面

List<User> getUserListByMap(Map<String,String> userMap);

編寫UserMapper.xml檔案

<select id="getUserListByMap" resultType="User" parameterType="Map">
    SELECT * FROM USER WHERE userName LIKE concat('%',#{userName},'%')
    and userRole=#{userRole}
</select>

編寫測試

SqlSession sqlSession=null;
List<User> userList=new ArrayList<User>(); try{
    sqlSession=MyBatisUtil.createSqlSession();
    Map<String,String> userMap=new HashMap<String,String>();
    userMap.put("userName","趙");
    userMap.put("userRole","3");
    userList=sqlSession.getMapper(UserMapper.class).getUserListByMap(userMap);
}catch (Exception ex){
    ex.printStackTrace();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:
        userList) {
    System.out.println(user.getUserName()+"\t"+user.getUserRole());
}

使用resultMap完成查詢結果的展現

先在User類中加入userRoleName屬性:private String userRoleName,及其相應的getter和setter方

編寫UserMapper.xml檔案,修改其中的getUserList方法

<select id="getUserList" resultMap="userList" parameterType="User">
    SELECT u.*,r.roleName FROM USER u,Role r WHERE u.userName LIKE concat('%',#{userName},'%')
    AND u.userRole=#{userRole} AND u.userRole=r.id
</select> 
新增id為userList的resultMap元素節點  
<resultMap id="userList" type="User">
    <result property="id" column="id"/>
    <result property="userCode" column="userCode"/>
    <result property="userName" column="userName"/>
    <result property="phone" column="phone"/>
    <result property="birthday" column="birthday"/>
    <result property="gender" column="gender"/>
    <result property="userRole" column="userRole"/>
    <result property="userRoleName" column="roleName"/>
</resultMap>

測試

SqlSession sqlSession=null;
List<User> userList=new ArrayList<User>(); try{
    sqlSession=MyBatisUtil.createSqlSession();
    User user=new User();
    user.setUserName("趙");
    user.setUserRole(3);
    userList=sqlSession.getMapper(UserMapper.class).getUserList(user); }catch (Exception ex){
    ex.printStackTrace();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}
for (User user:
        userList) {
    
System.out.println(user.getUserName()+"\t"+user.getUserRole()+"\t"+user.getUserRoleName());
}

resultMap元素的屬性值和子節點:
id屬性:唯一標識,此id值用於select元素resultMap屬性的引用
type屬性:表示該resultMap的對映結果型別
result子節點:用於標識一些簡答的屬性,其中column屬性表示從資料庫中查詢的欄位名,property則
表示查詢出來的欄位對應的賦值給實體物件的哪個屬性
resultType和resultMap的異同點及場景

  • 1.resultType直接表示返回型別,包括基本資料型別和複雜資料型別
  • 2.resultMap則是對外部resultMap定義的引用,對應外部resultMap的id
  • 3.MyBatis的每個查詢對映的返回型別都是resultMap,當我們提供的返回型別是resultType,會自動賦值
    給指定屬性
  • 4.resultMap自動對映界別預設對映級別為PARTIAL,在resultMap沒有做對映關聯時也能自動匹配。
    關閉方法:
<settings>
    <!--設定resultMap的自動對映級別為NONE(禁止自動匹配)-->
    <setting name="autoMappingBehavior" value="NONE"/> 
    </settings>

實現增刪改的操作

1使用insert完成增加操作
在介面中新增add()方法
int add(User user);
在對映檔案中編寫插入語句

<insert id="add" parameterType="User">
    INSERT INTO USER (userCode,userName,userPassword,gender,birthday,
      phone,address,userRole,createdBy,creationDate)
    VALUES (#{userCode},#{userName},#{userPassword},#{gender},#{birthday},
      #{phone},#{address},#{userRole},#{createdBy},#{creationDate})
</insert>

編寫測試程式碼

SqlSession sqlSession=null; try{
    sqlSession=MyBatisUtil.createSqlSession();
    User user=new User();
    user.setUserCode("testtt");
    user.setUserName("測試");
    user.setUserPassword("fajklfd");
    user.setGender(1);
    Date birthday=new SimpleDateFormat("yyyy-MM-dd").parse("1990-1-1");     user.setBirthday(birthday);
    user.setPhone("1228392324");
    user.setAddress("北京");
    user.setUserRole(3);
    user.setCreatedBy(1);
    user.setCreationDate(new Date());
    int count=sqlSession.getMapper(UserMapper.class).add(user);
    System.out.println("數量:"+count);
    sqlSession.commit();
}catch (Exception ex){
    ex.printStackTrace();
    sqlSession.rollback();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}

使用update完成修改

在介面中新增modify()方法
int modify(User user);
在對映檔案中編寫修改語句

<update id="modify" parameterType="User">
    UPDATE USER SET userCode=#{userCode},userName=#{userName},userPassword=# {userPassword},
    gender=#{gender},phone=#{phone},address=#{address},userRole=#{userRole},modifyBy=# {modifyBy},
    modifyDate=#{modifyDate},birthday=#{birthday}     WHERE id=#{id}
</update>

編寫測試程式碼

SqlSession sqlSession=null; try{
    sqlSession=MyBatisUtil.createSqlSession();
    User user=new User();
    user.setId(15);
    user.setUserCode("testtt");
    user.setUserName("測試修改");
    user.setUserPassword("fajklfd");
    user.setGender(1);
    Date birthday=new SimpleDateFormat("yyyy-MM-dd").parse("1990-1-1");
    user.setBirthday(birthday);
    user.setPhone("1228392324");
    user.setAddress("北京");
    user.setUserRole(3);     user.setCreateBy(1);
    user.setCreationDate(new Date());
    int count=sqlSession.getMapper(UserMapper.class).modify(user);
    //int i=2/0;//測試事務回滾
    System.out.println("數量:"+count);
    sqlSession.commit();
}catch (Exception ex){
    ex.printStackTrace();
    sqlSession.rollback();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}

使用@Param註解實現多引數入參

如果引數只有兩個,封裝成物件並不合適,多引數入參可讀性高。
在引數前增加@Param註解

int updatePwd(@Param("id")Integer id,@Param("userPassword")String pwd);

編寫修改語句

<update id="updatePwd">
    UPDATE USER  SET userPassword=#{userPassword} WHERE id=#{id}
</update>

編寫測試

SqlSession sqlSession=null; try{
    sqlSession=MyBatisUtil.createSqlSession();
    int id=15;
    String pwd="abc1223";
    int count=sqlSession.getMapper(UserMapper.class).updatePwd(id,pwd);
    //int i=2/0;//測試事務回滾
    System.out.println("數量:"+count);
    sqlSession.commit();
}catch (Exception ex){
    ex.printStackTrace();
    sqlSession.rollback();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}

使用delete完成刪除操作

編寫介面方法

int deleteUserById(@Param("id")Integer delId);

在對映檔案中編寫刪除語句

<delete id="deleteUserById">
    DELETE FROM USER  WHERE id=#{id}
</delete>

編寫測試

SqlSession sqlSession=null;
try{
    sqlSession=MyBatisUtil.createSqlSession();
    int id=15;
    int count=sqlSession.getMapper(UserMapper.class).deleteUserById(id);
    System.out.println("數量:"+count);
    sqlSession.commit();
}catch (Exception ex){
    ex.printStackTrace();
    sqlSession.rollback();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}

使用resultMap實現高階結果對映(表表關聯)

使用resultMap實現高階結果對映(表表關聯)

Role類
public class Role {
    private Integer id;
    private String roleCode;
    private String roleName;
    private Integer createdBy;
    private Date creationDate;
    private Integer modifyBy;
    private Date modifyDate;
    //省略getter和setter
}

修改pojo User類

public class User {
    private Integer id;             //id
    private String userCode;        //使用者編碼  
    private String userName;        //使用者名稱稱 
    private String userPassword;    //使用者密碼 
    private Integer gender;         //性別
    private Date birthday;          //出生日期
    private String phone;           //電話 
    private String address;         //地址
    private Integer userRole;       //使用者角色
    private Integer createdBy;       //建立者
    private Date creationDate;      //建立時間 
    private Integer modifyBy;       //更新者     private Date modifyDate;        //更新時間
    //private String userRoleName; 
    //使用者角色名稱     private Role role;
    //省略getter&setter方法
}
在UserMapper介面中新增方法
List<User> getUserListByRoleId(@Param("userRole")Integer roleId);

修改UserMapper.xml 增加getUserListByRoleId
xml <resultMap id="userRoleResult" type="User"> <id property="id" column="id"/> <result property="userCode" column="userCode"/> <result property="userName" column="userName"/> <result property="userRole" column="userRole"/> <association property="role" javaType="Role"> <id property="id" column="r_id"/> <result property="roleCode" column="roleCode"/> <result property="roleName" column="roleName"/> </association> </resultMap> <select id="getUserListByRoleId" parameterType="Integer" resultMap="userRoleResult"> SELECT u.*,r.id AS r_id,r.roleCode,r.roleName FROM user u,role r WHERE u.userRole=#{userRole} and u.userRole=r.id </select>
使用外部resultMap複用配置

<resultMap id="roleResult" type="Role">
    <id property="id" column="r_id"/>
    <result property="roleCode" column="roleCode"/>
    <result property="roleName" column="roleName"/>
</resultMap>
<resultMap id="userRoleResult" type="User">
    <id property="id" column="id"/>
    <result property="userCode" column="userCode"/>
    <result property="userName" column="userName"/>
    <result property="userRole" column="userRole"/>
    <association property="role" javaType="Role" resultMap="roleResult"/>
</resultMap>

collection 一對多關聯
建立pojo Addres.java

public class Address {     private Integer id;
    private String contact;
    private String addressDesc;
    private String postCode;
    private String tel;
    private Integer createdBy;
    private Date creationDate;
    private Integer modifyBy;
    private Date modifyDate;     private Integer userId;
    //省略getter和setter
}

修改User類增加地址列表屬性

List<Address>addressList;

編寫介面中的方法

List<User> getAddressListByUserId(@Param("id")Integer userId);

編寫對映檔案

<resultMap id="addressResult" type="Address">
    <id column="a_id" property="id"/>
    <result property="postCode" column="postCode"/>
    <result property="tel" column="tel"/>
    <result property="contact" column="contact"/>
    <result property="addressDesc" column="addressDesc"/>
</resultMap>
<resultMap id="userAddressResult" type="User">
    <id property="id" column="id"/>
    <result property="userCode" column="userCode"/>
    <result property="userName" column="userName"/>
    <collection property="addressList" ofType="Address" resultMap="addressResult"/>
</resultMap>

編寫測試

SqlSession sqlSession=null; try{
    sqlSession=MyBatisUtil.createSqlSession();
    List<User> userList=sqlSession.getMapper(UserMapper.class).getAddressListByUserId(1);     for (User user: userList) {
        System.out.println(user.getUserName());         List<Address> addresses=user.getAddressList();         for (Address address:
                addresses) {
            System.out.println("--- "+address.getContact());
        }
    }
}catch (Exception ex){
    ex.printStackTrace();
}finally {
    MyBatisUtil.closeSqlSession(sqlSession);
}

resultMap自動對映級別和MyBatis快取

autoMappingBehavior的三個級別
NONE:禁止自動匹配
PARTIAL:(預設)自動匹配所有屬性,有內部巢狀(assocition,collection)除外
FULL:自動匹配所有