mybatis的動態sql與核心對映
一:mybatis中如何使用動態sql:
MyBatis的強大特性之一便是它的動態 SQL。如果你有使用 JDBC 或其他類似框架的經驗,你就能體會到根據不同條件拼接 SQL 語句有多麼痛苦。拼接的時候要確保不能忘了必要的空格,還要注意省掉列名列表最後的逗號。有些時候,SQL語句where條件中,需要一些安全判斷,例如按某一條件查詢時如果傳入的引數是空,此時查詢出的結果很可能是空的,也許我們需要引數為空時,是查出全部的資訊。使用Oracle的序列、mySQL的函式生成Id。這時我們可以使用動態SQL。利用動態 SQL 這一特性可以徹底擺脫這種痛苦。通常使用動態 SQL 不可能是獨立的一部分,MyBatis 當然使用一種強大的動態 SQL 語言來改進這種情形,這種語言可以被用在任意的 SQL 對映語句中。動態 SQL 元素和使用 JSTL 或其他類似基於 XML 的文字處理器相似。MyBatis 採用功能強大的基於 OGNL 的表示式來消除其他元素。
MyBatis中用於實現動態SQL的元素主要有:
1、if和where
if就是簡單的條件判斷,利用if語句我們可以實現某些簡單的條件選擇。動態 SQL 通常要做的事情是有條件地包含 where 子句的一部分。
where元素的作用是會在寫入where元素的地方輸出一個where,另外一個好處是你不需要考慮where元素裡面的條件輸出是什麼樣子的,MyBatis會智慧的幫你處理。如果所有的條件都不滿足那麼MyBatis就會查出所有的記錄;如果輸出後是and這個單詞開頭的,MyBatis會把第一個單詞and忽略,當然如果是or開頭的,MyBatis也會把它忽略。此外,在where元素中你不需要考慮空格的問題,MyBatis會智慧的幫你加上。
2、choose(when,otherwise)
choose元素的作用就相當於JAVA中的switch語句,基本上跟JSTL中的choose的作用和用法是一樣的,通常都是與when和otherwise搭配的。
3、trim
trim元素的主要功能是可以在自己包含的內容前加上某些字首,也可以在其後加上某些字尾,與之對應的屬性是prefix和suffix;可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是prefixOverrides和suffixOverrides;正因為trim有這樣的功能,所以我們也可以非常簡單的利用trim來代替where元素的功能
4、set
set元素主要是用在更新操作的時候,它的主要功能和where元素其實是差不多的,主要是在set標籤包含的語句前輸出一個set。如果包含的語句是以逗號結束的話將會把該逗號忽略。如果set包含的內容為空的話則會出錯。有了set元素我們就可以動態的更新那些修改了的欄位,而不用每次更新全部欄位。
5、foreach
foreach的主要用在構建in條件中,它可以在SQL語句中迭代一個集合。foreach元素的屬性主要有item,index,collection,open,separator,close。
item表示集合中每一個元素進行迭代時的別名,index指定一個名字,用於表示在迭代過程中,每次迭代到的位置,open表示該語句以什麼開始,separator表示在每次進行迭代之間以什麼符號作為分隔符,close表示以什麼結束。
collection屬性用於指定傳入引數的型別。該屬性是必須指定的,在不同情況下,該屬性的值是不一樣的,主要有一下3種情況:
如果傳入的是單引數且引數型別是一個List型別的時候,collection屬性值為list。
如果傳入的是單引數且引數型別是一個array陣列的時候,collection的屬性值為array。
如果傳入的引數是多個的時候,我們就需要把它們封裝成一個Map了,當然單引數也可以封裝成map。實際上在傳入引數的時候,MyBatis也是把它封裝成一個Map的,List例項將會以“list”作為鍵,而陣列例項將會以“array”作為鍵。這個時候collection屬性值就是傳入的List或array物件在封裝自身的map裡面中的對應key。
具體使用:
1.通過resource載入單個的對映檔案UserMapper.xml
通過mapper介面載入單個mapper,要遵循一定的規範:
(1)前提是使用mapper代理開發(已經有4個規範)
(2)需要將mapper介面類名和mapper.xml對映檔名稱保持一致,且在同一目錄下
通過批量載入mapper(推薦使用):實現條件是
要滿足mapper介面載入對映檔案和使用mapper代理開發同時滿足
mybatis的核心輸入對映和輸出對映開始:
輸入對映:
通過parameterType指定輸入引數型別,型別可以是簡單型別、hashmap、pojo的包裝型別
輸出對映
1,resultType
使用resultType進行輸出對映時,只有查詢輸出結果列名和pojo中的屬性名一致才可以,對映成功
如果查詢出來的列名和pojo中的屬性名沒有一個一致的,就不會建立pojo物件
如果查詢出來的列名和pojo中的屬性名有一個一致,就會建立pojo物件
輸出pojo物件和pojo列表
不管是輸出的pojo單個物件還是一個列表(list中包含pojo),在mapper.xml中resultType指定的型別是一樣的
在mapper.java指定的方法返回值型別不一樣:
(1)輸出單個pojo物件,方法返回值是個單個物件型別
(2)輸出pojo物件list,方法返回值就是list物件型別
在動態代理物件中,是根據mapper方法的返回值型別來確定是呼叫selectOne(返回單個物件)還是selectList(返回集合物件)
2,resultMap
使用resultMap進行對映時,查詢結果列名和pojo的屬性名不一致時,resultMap會對列名和pojo屬性名進行對映,保證其成功對映
1—建立 User 類
package com.offcn.entity;
import java.util.Date;
import java.util.List;
public class User {
private List<Address> addressList;
public Role getRole() {
return role;
}
private Role role;
public List<Address> getAddressList() {
return addressList;
}
public void setAddressList(List<Address> addressList) {
this.addressList = addressList;
}}
2.第二部—定義介面UserMapper
package com.offcn.dao;
import com.offcn.entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface UserMapper {
List selectByName(User user);
/* 使用註解方式注入引數*/
/*List<User> selectByName(@Param("userName")
String userName, @Param("userRole") Integer userRole);*/
/*------*/
List<User> selectByMap(Map<String,String> map);
/*-------*/
List<User> selectByRole(User u);
/*-------*/
List<User> selectAddressByUserName(String userName);
/*---增加一個使用者--*/
int addUser(User user);
/*---修改一個使用者*/
int updateUser(User user);
/*-----查詢userRole的2或3的所有使用者,傳一個數組引數*/
List<User> selectArrayUser(Integer[] userRole);
List<User> selectArrayUser(List<Integer> userRole);
}
3.第三步
對映檔案UserMapper.xml配置 :
<mapper namespace="com.offcn.dao.UserMapper">
<!--這個id的名字必須與你的dao層方法名一樣-->
<!--prefix加字首,prefixOverrides去除第一個and關鍵詞,suffix加字尾,suffixOverrides去除最後一個符號或關鍵字-->
<select id="selectByName" resultType="User">
select u.*,r.roleName from smbms_user u,smbms_role r
<trim prefix="where" prefixOverrides="and" suffix="and u.userRole=r.id">
<if test="userRole!=null">
and userRole=#{userRole}
</if>
<if test="userName!=null and userName!=''">
and userName like concat ('%',#{userName},'%')
</if>
</trim>
</select>
<insert id="addUser" parameterType="User" >
insert into smbms_user(userName,userPassword,UserCode,gender,birthday)
values (#{userName},#{userPassword},#{userCode},#{gender},#{birthday})
/*插入*/
</insert>
<!--prefix 加上字首 -->
<update id="updateUser" parameterType="User">
update smbms_user
<trim prefix="set" suffixOverrides="," suffix="where id=#{id}">
<if test="userCode !=null">userCode=#{userCode},</if>
<if test="userName !=null">userName=#{userName},</if>
<if test="userPassword !=null">userPassword=#{userPassword},</if>
<if test="gender !=null">gender=#{gender},</if>
<if test="birthday !=null">birthday=#{birthday},</if>
</trim>
</update>
<!--<select id="selectByMap" parameterType="Map" resultType="User">
select u.*,r.roleName from smbms_user u,smbms_role r
where userName like concat ('%',#{uName},'%') and
userRole =#{uRole} and u.userRole=r.id
</select>-->
<!--resultMap的id與你select的resultMap的值對應-->
<!--type是代表你的返回值型別(可以給別名)-->
<resultMap id="selectByMapResult" type="User">
<!--property的id代表 標籤實體類的屬性名,column代表是你的資料庫列名-->
<!--兩種id必須相匹配,不匹配的時候兩種情況-->
<!--兩種情況:-->
<!--第一種:是你的標籤實體類的屬性名與你的資料庫列名相對應-->
<!--第二種:複雜查詢的時候(一對一,一對多)-->
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<result property="userRole" column="userRole"></result>
<result property="userPassword" column="userPassword"></result>
</resultMap>
<select id="selectByMap" parameterType="Map" resultMap="selectByMapResult">
select u.*,r.id from smbms_user u,smbms_role r
where userName like concat ('%',#{uName},'%') and
userRole =#{uRole} and u.userRole=r.id
</select>
<!--resultMap的id與下面的<select>標籤的resultMap的值一樣-->
<resultMap id="selectRoleMap" type="User">
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<result property="userRole" column="userRole"></result>
<!--配置一對一的關係,association拿到的是你的屬性名-->
<!--javaType代表你的返回型別-->
<association property="role" javaType="Role">
<id property="id" column="r_id"></id>
<result property="roleName" column="roleName"></result>
<result property="roleCode" column="roleCode"></result>
<!--如果下面select標籤裡的查詢語句u的id與r的id欄位名一致時,需要給r的id取一個別名r_id-->
</association>
</resultMap>
<!--resultMap的值自己定義-->
<select id="selectByRole" parameterType="User" resultMap="selectRoleMap">
select u.*,r.id as r_id,r.roleName,r.roleCode from smbms_user u,smbms_role r
where userName like concat ('%',#{userName},'%') and
userRole =#{userRole} and u.userRole=r.id
</select>
<!--根據名字查詢地址一對多的關係-->
<resultMap id="selectAddressMap" type="User">
<id property="id" column="id"></id>
<result property="userName" column="userName"></result>
<!--開始配置一對多的關係-->
<collection property="addressList" ofType="Address">
<!--<id property="id" column="id"></id>-->
<result property="addressDesc" column="addressDesc"></result>
<result property="contact" column="contact"></result>
</collection>
</resultMap>
<select id="selectAddressByUserName" parameterType="String" resultMap="selectAddressMap">
select u.*,a.addressDesc,a.contact from smbms_address a,smbms_user u
where a.userId=u.id and u.userName=#{userName}
</select>
<!--collection你要遍歷的型別 list是指List集合 array是指陣列 item你要自定義的條目名-->
<!--open以什麼開始 separator以什麼分割 close以什麼結束 -->
<!--#{uRole}的值與item的名字要一樣-->
<select id="selectArrayUser" resultType="User">
select * from smbms_user where userRole in
<foreach collection="list" item="uRole" open="(" separator="," close=")">
#{uRole}
</foreach>
</select>
第四部:
測試類:
/----動態sql–/
/*-查詢全部-*/
/*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
List<Address> addresses = mapper.selectAllAddress();
for (Address a :addresses
) {
System.out.println(a.getAddressDesc()+"--"+a.getContact());
}*/
/*----模糊c查詢----*/
/*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
Address address = mapper.selectOneAddress("李");
System.out.println(address.getContact()+"---");*/
/*--查詢一條--*/
/* SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
Address address = mapper.checkAddress(3);
System.out.println(address);*/
/*-----註解配置的對映------*/
/*查詢mysql表中所有Address的方法*/
/*SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
AddressMapper mapper = sqlSession.getMapper(AddressMapper.class);
List<Address> list = mapper.selectAllAddress();
for (Address aa:list) {
System.out.println(aa.getContact()+"###");
}*/
/*----------通過管理員名字模糊查詢所有使用者---------*/
/* SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setUserRole(3);
user.setUserName("孫");
List<User> list=mapper.selectByName(user);
for (User u:list
) {
System.out.println(u.getUserName()+"000");
}*/
SqlSession sqlSession= SqlSessionUtils.getSqlSessionUtils().sqlSession;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/*User user=new User();
user.setUserRole(3);
user.setUserName("孫");*/
/* Map<String,String> map=new HashMap<String,String>();
map.put("uName","孫");
map.put("uRole","3");*/
/*--如果你使用Map集合來進行傳參,鍵名必須與你UserMapper.xml檔案裡面的佔位符#{}的值必須一致--*/
/* List<User> list=mapper.selectByRole(user);
for (User u:list) {
System.out.println(u.getUserName()+"---"+u.getUserRole());
Role role = u.getRole();
System.out.println(role.getRoleName()+"--"+role.getRoleCode());
}*/
/*---一對多:查詢某一個人的所有地址---*/
/* List<User> list = mapper.selectAddressByUserName("張華");
for (User u:list
) {
System.out.println(u.getUserName()+"\t");
List<Address> addressList=u.getAddressList();
for (Address a:addressList
) {
System.out.println(a.getContact()+"--"+a.getAddressDesc());
}
}*/
/* List<User> list = mapper.selectByName("張", null);
for (User u:list
) {
System.out.println(u.getUserName()+"--"+u.getUserRole());
}*/
/*--增加一個--*/
/*User user=new User();
user.setUserName("vvv");
user.setBirthday(new Date());
user.setUserCode("asd");
user.setUserPassword("2222");
user.setGender(2);
int i = mapper.addUser(user);
System.out.println(i);*/
/*---修改一個---*/
/* User user=new User();
user.setUserName("尼瑪");
user.setGender(2);
user.setId(2);
int i = mapper.updateUser(user);
System.out.println(i);*/
/*User user=new User();
user.setUserName("尼瑪");
List<User> list = mapper.selectByName(user);
for (User u:list
) {
System.out.println(u.getUserName());
}*/
List<Integer> list1=new ArrayList<Integer>();
list1.add(2);
list1.add(3);
List<User> list = mapper.selectArrayUser(list1);
for (User u:list
) {
System.out.println(u.getUserName());
}