MyBatis的xml常用的那些写法,还记得多少?
众所周知,MyBatis有一个很大的特点,那就是动态SQL。如果前端是在App上的,更能感觉到动态SQL的好处,App页面的特点是面积小,字段少,一个表中的数据可能会分散在好多个页面上进行更新,如果是使用Hibernate,那就比较惨,更新一次痛苦一次,代价沉重。
MyBatis动态SQL语句的优点就在这里,想更新哪个字段就更新那个字段,无需太多。不仅在更新的时候,有这个便利,在复杂条件查询的时候,更能体验出动态SQL的好用。
MyBatis采用功能强大的基于OGNL对象导航图语言(Object Graph Navigation Language)的表达式在xml中构建强大的动态SQL语句。在以往拼接语句时,一个小小的标点符号或连接词,都需要加判断是加还是不加,很累人,在MyBatis中只要使用了它的语法,这些就不要考虑太多,它帮你解决。
下面针对常用的场景写一些demo。
环境说明:
springboot2.1.4
mybatis和springboot的集成
druid数据源
mysql数据库
首先,pom文件中引入必须的架包;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- druid数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!-- mysql数据库 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis和spring boot的集成-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
第二,生成xml和dao文件,不会生成的,可以参照以前的文章。
第三,Controller中写demo;
/**
* mybatis xml语法测试demo
* @author 程就人生
* @date 2019年9月19日
*/
@RequestMapping("/test")
@RestController
public class TestController {
//这里忽略service这一业务层,如果需要事务处理还是需要service的,直接调用dao层
@Autowired
private TestMapper testMapper;
/**
* 新增一个
* @return
*
*/
@GetMapping("/insert")
public Object insert(){
Test test = new Test();
test.setUserId("123456aa");
test.setUserName("程就人生");
int effectRow = testMapper.insertSelective(test);
System.out.println("数据库执行影响行数:" + effectRow + "行。");
return "数据库执行影响行数:" + effectRow + "行。";
}
/**
* 批量新增
* @return
*
*/
@GetMapping("/insertBatch")
public Object insertBatch(){
List<Test> testList = new ArrayList<Test>();
Test test=null;
for(int i=0;i<20;i++){
test = new Test();
test.setUserId("aabbccdd" + i);
test.setUserName("程就人生" + i);
test.setStatus((byte)1);
test.setUserMobile("1381111111" + i);
test.setCreateDate(new Date());
test.setCreateUser("程就人生");
test.setUpdateDate(new Date());
test.setUpdateUser("程就人生");
test.setUserBirthday(new Date());
test.setUserPwd("123456");
testList.add(test);
}
int effectRow = testMapper.insertBatch(testList);
System.out.println("数据库执行影响行数:" + effectRow + "行。");
return "数据库执行影响行数:" + effectRow + "行。";
}
/**
* 修改测试
* @return
*
*/
@GetMapping("/update")
public Object update(){
Test test = new Test();
test.setUserId("123456aa");
test.setUserName("愉快人生");
int effectRow = testMapper.updateByPrimaryKeySelective(test);
System.out.println("数据库执行影响行数:" + effectRow + "行。");
return "数据库执行影响行数:" + effectRow + "行。";
}
/**
* 传递多个参数
* @return
*
*/
@GetMapping("/one")
public Object search(){
List<Test> testList = testMapper.selectByOnlyField("愉快人生","123456aa");
return testList;
}
/**
* 传递的参数为map集合
* @return
*
*/
@GetMapping("/two")
public Object search1(){
Map<String,Object> map = new HashMap<String,Object>();
map.put("userId", "123456aa");
map.put("userName", "愉快人生");
return testMapper.selectOnlyField(map);
}
/**
* 传递双重集合,map集合里面是map集合,或者对象里面是map集合
* @return
*
*/
@GetMapping("/two1")
public Object search11(){
Map<String,Object> pmap = new HashMap<String,Object>();
Map<String,Object> map = new HashMap<String,Object>();
map.put("userId", "123456aa");
map.put("userName", "愉快人生");
pmap.put("condition", map);
return testMapper.selectOnlyField1(pmap);
}
/**
* 返回map集合
* @return
*
*/
@GetMapping("/three")
public Object search2(){
return testMapper.selectByUserNameAndUserId();
}
/**
* 联合查询加别名,如何加?
* @return
*
*/
@GetMapping("/four")
public Object search3(){
return testMapper.searchAlias();
}
}
第四,dao文件中填补方法,这里只拷贝了后面自己写的方法,生成的忽略;
/**
* 批量新增,参数用@Param标注时,xml中接收的collection为标注的名称,否则默认为list
* @param testList
* @return
*
*/
int insertBatch(List<Test> testList);
/**
* 多个参数的绑定
* @param username
* @param userid
* @return
*
*/
List<Test> selectByOnlyField(@Param("userName")String username, @Param("userId")String userid);
/**
* map参数的绑定
* @param username
* @param userid
* @return
*
*/
List<Test> selectOnlyField(Map<String,Object> paramMap);
/**
* 传递参数,map集合中嵌套map集合
* @param paramMap
* @return
*
*/
List<Test> selectOnlyField1(Map<String,Object> paramMap);
/**
* 返回map集合
* @return
*
*/
List<Map<String,Object>> selectByUserNameAndUserId();
/**
* 联合查询加别名
* @return
*
*/
List<Map<String,Object>> searchAlias();
第五,xml查询语句填充。
<select id="selectByOnlyField" resultMap="BaseResultMap" > <!-- 返回结果集为BaseResultMap,BaseResultMap 对应上的id为BaseResultMap的sql -->
select
<include refid="Base_Column_List" /><!-- Base_Column_List为表中的所有字段,也就是查询后返回的字段 -->
from test
<where> <!-- 使用mybatis自带的where标签,可以不用担心哪个条件前有and,这个where标签会自动过滤掉 -->
<if test="userName!=null">
and user_name like CONCAT('%', #{userName,jdbcType=VARCHAR}, '%') <!-- 模糊查询,使用concat连接符 -->
</if>
<if test="userId != null">
and user_id = #{userId,jdbcType=VARCHAR}
</if>
</where>
</select>
<sql id="Search_Criteria">
<if test="userName != null and userName != ''">
and user_name like CONCAT('%', #{userName}, '%')
</if>
<if test="userId != null and userId != ''">
and user_id = #{userId}
</if>
</sql>
<select id="selectOnlyField" parameterType="java.util.Map" resultMap="BaseResultMap" > <!-- 参数为map集合 -->
select
<include refid="Base_Column_List" />
from test
<where>
<include refid="Search_Criteria"></include> <!-- 绑定查询条件 -->
</where>
</select>
<sql id="Search_Criteria1">
<bind name="userName" value="condition['userName']" />
<bind name="userId" value="condition['userId']" />
</sql>
<select id="selectOnlyField1" parameterType="java.util.Map" resultMap="BaseResultMap" > <!-- 参数为map集合中嵌套map集合-->
<include refid="Search_Criteria1"></include> <!-- 绑定查询条件 -->
select
<include refid="Base_Column_List" />
from test
<where>
<if test="userName != null and userName != ''">
and user_name like CONCAT('%', #{userName}, '%')
</if>
<if test="userId != null and userId != ''">
and user_id = #{userId}
</if>
</where>
</select>
<select id="selectByUserNameAndUserId" resultType="java.util.Map" ><!-- 返回结果为list集合时,这里需要填写list中的数据类型 -->
select user_id, user_name
from
test
</select>
<sql id="Base_Column_List1" >
${alias}.user_id as userId
</sql>
<sql id="Base_Column_List2" >
${alias}.user_name as userName
</sql>
<select id="searchAlias" resultType="java.util.Map" >
select
<include refid="Base_Column_List1" ><property name="alias" value="A"/></include>, <!-- 可以根据需要为每个表加别名 -->
<include refid="Base_Column_List2" ><property name="alias" value="A"/></include>
from test as A
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String" >
delete from test
where user_id = #{userId,jdbcType=VARCHAR}
</delete>
<insert id="insert" parameterType="com.example.demo.entity.Test" > <!-- 参数为实体类时 -->
insert into test (user_id, user_pwd, user_name,
user_mobile, update_user, status,
create_user, user_birthday, create_date,
update_date)
values (#{userId,jdbcType=VARCHAR}, #{userPwd,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR},
#{userMobile,jdbcType=VARCHAR}, #{updateUser,jdbcType=VARCHAR}, #{status,jdbcType=TINYINT},
#{createUser,jdbcType=VARCHAR}, #{userBirthday,jdbcType=TIMESTAMP}, #{createDate,jdbcType=TIMESTAMP},
#{updateDate,jdbcType=TIMESTAMP})
</insert>
<insert id="insertBatch" parameterType="java.util.List" > <!-- 批量新增,参数为list集合,默认使用list接收,除非dao中用@Param标注了,则要保持一致 -->
insert into test (user_id, user_pwd, user_name,
user_mobile, update_user, status,
create_user, user_birthday, create_date,
update_date)
values
<foreach collection="list" index="index" item="item" separator="," > <!-- open="(" close=")" 根据需要添加-->
(#{item.userId,jdbcType=VARCHAR}, #{item.userPwd,jdbcType=VARCHAR}, #{item.userName,jdbcType=VARCHAR},
#{item.userMobile,jdbcType=VARCHAR}, #{item.updateUser,jdbcType=VARCHAR}, #{item.status,jdbcType=TINYINT},
#{item.createUser,jdbcType=VARCHAR}, #{item.userBirthday,jdbcType=TIMESTAMP}, #{item.createDate,jdbcType=TIMESTAMP},
#{item.updateDate,jdbcType=TIMESTAMP})
</foreach>
</insert>
最后,测试,对各个方法进行测试。
批量新增结果图
查询结果图
总结
这点小东西整理了一个晚上,全凭想,平时用到了也没有好好记录下来,当要一点点回忆时,真想不起来。更多的使用方法,还是参考文档吧。
这个demo写的很简单,service也省略了,配置文件里只是进行了简单的数据库配置和xml扫描路径的配置,如果启动项目的时候找不到dao,记得在启动文件里加一句配置。
@MapperScan(value = "com.example.demo.dao") //防止dao注入失败
参考资料:
http://www.dba.cn/book/
http://www.dba.cn/book/mybatis/
https://mybatis.org/mybatis-3/zh/index.html