1.MyBatis动态SQL
MyBatis 的强大特性之一便是它的动态 SQL,即拼接SQL字符串。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
2.动态SQL标签:if,choose (when, otherwise),trim (where, set),foreach
2.1.If标签
<select id="getUsersByNameAge" resultType="User" parameterType="User">
SELECT * FROM USER
WHERE 1=1
AND uname LIKE "%"#{uname}"%"
AND uage = #{uage}
</select>
注:if标签一般用于非空验证,如上例,若id为空,if标签里的代码,将不会执行,反之,则会执行。
2.2.Where标签
<!-- 根据uname,uage查询User-->
<select id="getUsersByNameAge" resultType="User">
SELECT * FROM USER
<!-- where:表示标签内部为where条件语句,会自动去除第一个前置and关键字-->
<where>
<!-- if:判断标签
test:判断,boolean类型表达式,如果为真执行标签中间内容,反之不执行-->
<if test="uname!=null and uname!=''">
AND uname LIKE "%"#{uname}"%"
</if>
<if test="uage!=null and uage!=''">
AND uage = #{uage}
</if>
</where>
</select>
2.3.Sql片段
<mapper namespace="mapper.UserMapper">
<!-- sql:sql片段,标签内部文本为sql语句片段
id:sql片段标记
-->
<sql id="cols">
uid,uname,uage
</sql>
<!-- 根据uname,uage查询User-->
<select id="getUsersByNameAge" resultType="User">
<!-- include: 引用sql片段
refid:sql片段的id-->
SELECT <include refid="cols"/> FROM USER
<where>
<if test="uname!=null and uname!=''">
AND uname LIKE "%"#{uname}"%"
</if>
<if test="uage!=null and uage!=''">
AND uage = #{uage}
</if>
</where>
</select>
</mapper>
2.4.foreach标签
<select id="getUsersByIds" resultType="User" parameterType="Queryvo" >
SELECT uid,uname,uage FROM USER WHERE uid
<!-- foreach :遍历集合
collection:集合类型(注:不是属性或变量名)
(1)传递简单参数:
遍历为数组类型:array
list类型:list
(2)传递对象包装类:直接写对应的属性名即可,不需要区分集合类型
separator:分隔符(最后一个元素不加)
item:遍历时被遍历出的元素的变量名
open: 遍历开始前的包裹内容
close:遍历结束后的包裹内容
index:索引
-->
<!--<foreach collection="list" separator="," item="id" open="IN (" close=")">-->
<foreach collection="ids2" separator="," item="id" open="IN (" close=")">
${id}
</foreach>
;
</select>
3.关联查询
3.1 一对一查询
方式1:自动映射
<!-- 一对一:自动映射 -->
<select id="findOrdersAndUser1" resultType="com.dml.pojo.CustomerOrders">
select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id;
</select>
UserMapper.java
@Test
public void testFindOrdersAndUser1() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<CustomerOrders> list = mapper.findOrdersAndUser1();
for (CustomerOrders co : list) {
System.out.println(co.getUsername() +"======="+co.getId() +"=======" +co.getUid());
}
}
CustomerOrders.java
public class CustomerOrders extends Orders{
private int uid;
private String username;// 用户姓名
private String sex;// 性别
private Date birthday;// 生日
private String address;// 地址
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
方法2:手动映射
<!--
id:resultMap的唯一标识
type:将查询出的数据放入这个指定的对象中
注意:手动映射需要指定数据库中标的字段名与java中pojo类的属性名称的对应关系
-->
<resultMap type="com.dml.pojo.Orders" id="orderAndUserResultMap">
<!-- id标签指定主键字段对应关系
column:列,数据库中的字段名称
property:属性,java中pojo中的属性名称
-->
<id column="id" property="id"/>
<!-- result:标签指定非主键字段的对应关系 -->
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<!-- 这个标签指定单个对象的对应关系
property:指定将数据放入orders中的user属性中
javaType:user属性的类型
-->
<association property="user" javaType="com.dml.pojo.User">
<id column="uid" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
select a.*,b.id uid,username,birthday,sex,address from orders a,user b where a.user_id = b.id;
</select>
UserMapper.java
//一对一:手动映射
public List<Orders> findOrdersAndUser2();
UserMapperTest.java
public void testFindOrdersAndUser2() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List<Orders> list = mapper.findOrdersAndUser2();
for (Orders co : list) {
System.out.println(co.getUser().getUsername() +"======="+co.getId() +"=======" +co.getUser().getId());
}
}
3.2 一对多查询
<resultMap type="com.dml.pojo.User" id="userAndOrdersResultMap">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<!-- 指定对应的集合对象关系映射
property:将数据放入User对象中的ordersList属性中
ofType: 指定ordersList属性的泛型类型
-->
<collection property="ordersList" ofType="com.dml.pojo.Orders">
<id column="oid" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
<select id="findUserAndOrders" resultMap="userAndOrdersResultMap">
select a.*,b.id oid,user_id,number,createtime from user a,orders b where a.id = b.user_id
</select>
UserMapper.java
//一对多
public List findUserAndOrders();
UserMapperTest.java
//一对多
@Test
public void testFindUserAndOrders() throws Exception{
SqlSession openSession = factory.openSession();
//通过getMapper方法来实例化接口
UserMapper mapper = openSession.getMapper(UserMapper.class);
List list = mapper.findUserAndOrders();
for (User user : list) {
System.out.print(user.getId() +"="+ user.getUsername() +"=");
List list2 = user.getOrdersList();
for (Orders orders : list2) {
System.out.print(orders.getId() + “===”);
}
System.out.println();
}