如何快速上手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:自動匹配所有