动态 SQL
动态 SQL 语句是在应用程序运行时被编译和执行的,如,一个客户一个 web 网站,输入姓名,手机号
等...条件名称 访问数据库的时候,用户输入的 SQL 语句是不确定性的,因此 SQL 语句只能被动态地编译。动态
SQL 的应用的场景很多,因此应用程序都使用动态 SQL来操作。(根据不同的条件需要执行不同的 SQL 命令)
If
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分
dao层
java
/**
* 动态sql
* 当字段值不为空以字段查询条件,当字段值为空查询所有
* @param bookModel
* @return
*/
List<BookModel> getBookListByIf(BookModel bookModel);
mapper
xml
<select id="getBookListByIf" parameterType="model.BookModel" resultType="model.BookModel">
select * from book where 1=1
<!-- 如果name条件为空,下面语句不会执行,只会执行上面语句 -->
<if test="name != null and name != ''">
and name = #{name}
</if>
</select>
测试
java
//main方法中调用
BookModel bookModel = new BookModel();
//不设置书的名称,查询所有数据
//设置书的名称,只查询书名的数据
bookModel.setName("大头儿子小头爸爸");
getBookListByIf(bookModel);
//方法
public static void getBookListByIf(BookModel bookModel) throws Exception{
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<BookModel> bookListByIf = mapper.getBookListByIf(bookModel);
for (BookModel book : bookListByIf){
System.out.println(book);
}
}
动态sql模糊匹配
dao层
java
/**
* 模糊查询所有数据
* @param bookModel 根据name模糊查询
* @return
*/
List<BookModel> getBookListByLikeName(BookModel bookModel);
mapper
xml
<select id="getBookListByLikeName" parameterType="model.BookModel" resultType="model.BookModel">
select * from book where 1=1
<if test="name != null and name != ''">
and name like concat('%',#{name},'%')
</if>
</select>
测试
java
//main方法中调用
getBookListByLikeName("小");
//方法
public static void getBookListByLikeName(String name) throws Exception{
BookModel bookModel = new BookModel();
bookModel.setName(name);
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<BookModel> bookList = mapper.getBookListByLikeName(bookModel);
for (BookModel book : bookList){
System.out.println(book);
}
}
where
where 有内容会则生成 where 关键字,如果没有内容则不生成 where 关键字
dao层
java
/**
* where查询
* @param bookModel
* @return
*/
List<BookModel> getBookListByWhere(BookModel bookModel);
mapper
xml
<select id="getBookListByWhere" parameterType="model.BookModel" resultType="model.BookModel">
select * from book
<where>
<!-- 如果name不为空 -->
<!-- select * from book where name like '%nameValue%' -->
<if test="name != null and name !=''">
name like concat('%',#{name},'%')
</if>
<!-- 如果price不为空 -->
<!-- select * from book where name like '%name%' and price = priceValue -->
<if test="price != null and price != ''">
and price = #{price}
</if>
</where>
</select>
测试
java
//main方法中调用
getBookListByWhere("大");
//方法
public static void getBookListByWhere(String name) throws Exception{
BookModel bookModel = new BookModel();
bookModel.setName(name);
//添加price,判断两个条件
//bookModel.setPrice(211.0);
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<BookModel> bookList = mapper.getBookListByWhere(bookModel);
for (BookModel book : bookList){
System.out.println(book);
}
}
choose,when,otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
dao层
java
/**
* choose,when,otherwise
* 只要三者中有一个成立,其他都不执行。
* @param bookModel
* @return
*/
List<BookModel> getBookListByChoose(BookModel bookModel);
mapper
xml
<select id="getBookListByChoose" parameterType="model.BookModel" resultType="model.BookModel">
select * from book
<where>
<choose>
<!-- 如果name不为空 -->
<!-- select * from book where name like '%nameValue%' -->
<when test="name != null and name != ''">
name like concat('%',#{name},'%')
</when>
<!-- 如果name为空 price不为空 -->
<!-- select * from book where price = priceValue -->
<when test="price != null and price != ''">
price = #{price}
</when>
<!-- 如果name为空 price为空 -->
<!-- select * from book where 1=1 -->
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
测试
java
//main中调用
getBookListByChoose("大");
//方法
public static void getBookListByChoose(String name) throws Exception{
BookModel bookModel = new BookModel();
bookModel.setName(name);
//虽然添加了price,但是只会执行name的查询条件,如果都没有条件执行,执行最后的otherwise里的条件,相当于switch
//bookModel.setPrice(211.0);
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<BookModel> bookList = mapper.getBookListByChoose(bookModel);
for (BookModel book : bookList){
System.out.println(book);
}
}
set
dao层
java
/**
* 动态修改信息
* @param bookModel
* @return
*/
int updateBookBySqlSet(BookModel bookModel);
mapper
xml
<update id="updateBookBySqlSet" parameterType="model.BookModel">
update book
<set>
<!-- 如果java测试类的name,price都不写入,注释掉,然后mapper的<set>自然两个if都不
进入,sql就会出现问题,因此加入id=#{id} -->
id = #{id},
<if test="name != null and name != ''">
name=#{name},
</if>
<!-- 如果添加额外的修改条件,却没给赋值,会赋值默认值 -->
<!-- 如果没有添加额外的修改条件,数据库本身的值不变,把下面的if注释掉,看看数据库的两种情况 -->
<if test="price != null and price != null">
price=#{price},
</if>
</set>
where id = #{id}
</update>
测试
java
//main中调用
updateBookBySqlSet();
//方法
public static void updateBookBySqlSet() throws Exception{
BookModel bookModel = new BookModel();
bookModel.setName("假如给我三天光明");
bookModel.setId(9);
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
int i = mapper.updateBookBySqlSet(bookModel);
sqlSession.commit();
System.out.println(i > 0 ? "修改成功" : "修改失败");
}
foreach
- 使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
- foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符。
- 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值
dao层
java
/**
* 根据指定id查询,比如查询id为5,6,7的数据
* @param ids
* @return
*/
List<BookModel> getBookByIn(int[] ids);
mapper
xml
<select id="getBookByIn" resultType="model.BookModel">
select * from book where id in
<foreach collection="array" item="id" index="i" open="(" separator="," close=")">
#{id}
</foreach>
</select>
测试
java
//main方法中调用
getBookByIn();
//方法
public static void getBookByIn() throws Exception{
int[] ids = {5,6,7};
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<BookModel> books = mapper.getBookByIn(ids);
for (BookModel book : books) {
System.out.println(book);
}
}
resultMap(解决数据库字段与实体类属性名不匹配问题)
mapper.xml文件
xml
<!-- 如果数据库字段名和实体类的属性名一致,可以不用配置resultMap,mybatis会隐式自动的创建一个 ResultMap -->
<!-- 结果映射 -->
<!-- id: resultMap的别名,唯一标识,由数据库操作调用 -->
<!-- type: 指定类型 -->
<resultMap id="book" type="model.BookModel">
<!-- id:指定和数据表主键字段对应的标识属性 -->
<!-- property:property表示实体类的属性 -->
<!-- column:数据库的字段名 -->
<!-- result:指定结果集字段和实体类属性的映射关系 -->
<id property="id" column="t_id" />
<result property="name" column="t_name"/>
<result property="price" column="t_price"/>
<result property="num" column="t_num"/>
</resultMap>
<!-- resultMap:引入resultMap的id,作为返回值类型 -->
<select id="findAll" resultMap="book">
select * from book;
</select>
第二种解决数据库字段名与实体类属性名不匹配方法
xml
<!-- 我们可以在sql语句中直接设置别名,mybtais会自动隐式映射 -->
<select id="findAll" resultMap="book">
select
t_id as id,
t_name as name,
t_price as price,
t_num as num
from book;
</select>
多表查询
dao层
java
List<Map<String,Object>> findPurBooMap();
mapper
xml
<select id="findPurBooMap" resultType="map">
select p.id,p.`name`,p.bid,b.id `book.id`,b.bookName `book.bookName`,b.auth
`book.auth`,b.price `book.price`,b.publish `book.publish`
from purchaser p LEFT JOINbook b
ON b.id = p.id
</select>
测试
java
public static void findPurBooMap() throws Exception{
SqlSession sqlSession = JDBCUtil.getSqlSession();
BookDao mapper = sqlSession.getMapper(BookDao.class);
List<Map<String,Object>> maps = mapper.findPurBooMap();
for (Map<String, Object> map : maps) {
for (Object string : map.keySet()){
System.out.println(string+":"+map.get(string));
}
}
}