动态sql
通过mybatis提供的各种标签方法实现动态拼接sql。
需求:根据性别和名字查询用户
查询sql:select * from user WHERE 1=1 and uname LIKE “%刘%” and uage = 20
If标签
Mapper.xml文件
UserMapper.xml配置sql,如下:(根据姓名模糊,年龄查询)
SELECT * FROM USER
WHERE 1=1
AND uname LIKE “%”#{uname}"%"
AND uage = #{uage}
Mapper接口
编写Mapper接口,如下图:
public interface UserMapper {
/**
* 根据uname模糊,uage 进行查询
*/
List getUsersByNameAge(User user);
}
测试方法
在UserMapperTest添加测试方法,如下:
/**
- 测试sql动态拼接
*/
private void fun1() {
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List userList =
mapper.getUsersByNameAge(new User(null, “赵”, 30));
for(User user : userList){
System.out.println(user);
}
}
使用if标签
改造UserMapper.xml,如下:
SELECT * FROM USER
WHERE 1=1
AND uname LIKE “%”#{uname}"%"
AND uage = #{uage}
注意字符串类型的数据需要要做不等于空字符串校验。
Where标签
上面的sql还有where 1=1 这样的语句,很麻烦
可以使用where标签进行改造
改造UserMapper.xml,如下
SELECT * FROM USER AND uname LIKE "%"#{uname}"%" AND uage = #{uage}Sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出来,作为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.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace
例如下图
foreach标签
向sql传递数组或List,mybatis使用foreach解析,如下:
根据多个id查询用户信息
查询sql:
SELECT * FROM user WHERE id IN (1,10,24)
改造QueryVo
如下图在pojo中定义list/数组属性ids存储多个用户id,并添加getter/setter方法
Mapper.xml文件
UserMapper.xml添加sql,如下:
<foreach collection="ids2" separator="," item="id" open="IN (" close=")">
${id}
</foreach>
;
测试方法如下图:
/**
-
测试foreach2
/
private void fun3() {
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
/ Integer[] ids = {1,3,4,6,18,11};
queryVo.setIds1(ids);*/List ids = new ArrayList();
ids.add(1);
ids.add(2);
ids.add(3);
queryVo.setIds2(ids);
List userList = mapper.getUsersByIds(queryVo);
for(User user : userList){
System.out.println(user);
}
}
/** -
测试foreach1
*/
private void fun2() {
SqlSession sqlSession = factory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/* Integer[] ids = {1,3,4,6,18,11};
List userList = mapper.getUsersByIds(ids);
for(User user : userList){
System.out.println(user);
}*/
List ids = new ArrayList();
ids.add(1);
ids.add(2);
ids.add(3);
List userList = mapper.getUsersByIds(ids);
for(User user : userList){
System.out.println(user);
}
}
关联查询
商品订单数据模型
一对一查询
需求:查询所有订单信息,关联查询下单用户信息。
注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
sql语句:
SELECT user.uid,uname,uage,oid,oname,odate
FROM order1 LEFT JOIN USER
ON order1.uid
=user.uid
方法一:使用resultType
使用resultType,改造订单pojo类,此pojo类中包括了订单信息和用户信息
这样返回对象的时候,mybatis自动把用户信息也注入进来了
改造pojo类
OrderUser类继承Order类后OrderUser类包括了Order1类的所有字段,只需要定义用户的信息字段即可,如下:
public class OrderUser extends Order1 implements Serializable {
static final long serialVersionUID = 42L;
private String uname;
private Integer uage;
…… ……
}
OrderMapper.xml
在UserMapper.xml添加sql,如下
SELECT user.uid,uname,uage,oid,oname,odate
FROM user RIGHT JOIN order1
ON order1.uid
=user.uid
Mapper接口
在UserMapper接口添加方法,如下图:
测试方法:
在UserMapperTest添加测试方法,如下:
/**
-
测试
-
方法一(扩充原实体类)查询order信息对应的信息及用户信息
*/
private void fun1() {
// 4.
SqlSession sqlSession = factory.openSession();
//
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);List orderUserList = mapper.getOrderUser();
for(OrderUser ou : orderUserList){
System.out.println(ou.getOname() + " ==" + ou.getUname());
}
sqlSession.close();
}