目录
1.单个参数:------------>八大基础类型与String类型
1.传递String的参数,必须使用@Param方式,并且指明参数名
2.在service接口,方法应该要将@param()去除掉,只留下变量名,在mapper层可以留下@param(),以防万一,防止报错
注: (1)mybatis中使用OGNL表达式传递参数 (2) 优先使用#{...} (3) ${...}方式存在SQL注入风险
案例③:使用resultType返回Map,适用于多表查询返回结果集,object>
为什么要重写mybatis的分页? Mybatis的分页功能很弱,它是基于内存的分页(查出所有记录再按偏移量offset和边界limit取结果),在大数据量的情况下这样的分页基本上是没有用的
5.在BookMapper.xml文件中进行sql语句的编写
8.在你需要进行分页的Mybatis方法前调用PageHelper.startPage静态方法即可,紧跟在这个方法后的第一个Mybatis查询方法会被进行分页
allowMultiQueries=true 允许一条SQL语句包含多个执行SQL以分号;分隔,是必须添加的
动态sql是指在进行sql操作的时候,传入的参数对象或者参数值,根据匹配的条件,有可能需要动态的去判断是否为空,循环,拼接等情况;
①:在BookMapper类定义包含if标签方法
- //if标签
- List
queryBookByIf(Book book);
②:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByIf" resultType="com.zking.model.Book">
- select
- <include refid="Base_Column_List">include>
- from t_book where 1=1
- <if test="null!=btype and ''!=btype">
- and btype= #{btype}
- if>
- select>
当满足test条件时,才会将if标签内的sql语句拼接上去
③:在iBookService类编写代码
- //mybatis之if标签
- List
queryBookByIf(Book book);
④:进行 junit4单元测试
------测试带type类型的查询:
- @Test
- //mybatis之if标签
- public void queryBookByIf(){
- List
bookList = iBookService.queryBookByIf(Book.builder().btype("历史").build()); - bookList.forEach(System.out::println);
- }
测试结果如下: 
查看sql语句:

---测试不type类型的查询:
- @Test
- //mybatis之if标签
- public void queryBookByIf(){
- List
bookList = iBookService.queryBookByIf(Book.builder().build()); - bookList.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

trim标签属性:
| prefix | 前缀 |
| suffix | 后缀 |
| suffixOverride | 去除后缀指定的字符 |
| prefixOverrides | 去除前缀指定的字符 |
①:在BookMapper类定义包含trim标签方法
int insertSelective(Book record);
②:在BookMapper.xml文件中进行sql语句的编写
- <insert id="insertSelective" parameterType="com.zking.model.Book" >
- insert into t_book
- <trim prefix="(" suffix=")" suffixOverrides="," >
- <if test="bid != null" >
- bid,
- if>
- <if test="bname != null" >
- bname,
- if>
- <if test="bprice != null" >
- bprice,
- if>
- <if test="btype != null" >
- btype,
- if>
- trim>
- <trim prefix="values (" suffix=")" suffixOverrides="," >
- <if test="bid != null" >
- #{bid,jdbcType=INTEGER},
- if>
- <if test="bname != null" >
- #{bname,jdbcType=VARCHAR},
- if>
- <if test="bprice != null" >
- #{bprice,jdbcType=INTEGER},
- if>
- <if test="btype != null" >
- #{btype,jdbcType=VARCHAR},
- if>
- trim>
- insert>
- foreach标签
foreach标签属性:
| collection | 被遍历的集合或数组 |
| item | 每次循环遍历的集合名 |
| separator | 每次循环的分隔符 |
| index | 下标 |
| open | 开始位置 |
| close | 关闭位置 |
①:编写一个类,储存需要遍历的集合或者数组
- package com.zking.vo;
-
- import com.zking.model.Book;
- import lombok.Data;
-
- import java.util.List;
-
- /**
- * @author 唐渊
- * @create 2022-07-23 9:26
- */
- @Data //getter/setter/toString
- public class BookVo extends Book {
- //foreach标签需要遍历的list集合
- private List
ids; -
-
- }
②:在BookMapper类定义包含foreach标签方法
- //foreach标签
- List
queryBookByForeach(BookVo bookVo);
③:在BookMapper.xml文件中进行sql语句的编写
(1)方式一:
- <select id="queryBookByForeach" resultType="com.zking.model.Book">
- select
- <include refid="Base_Column_List">include>
- from t_book where 1=1 and bid in
- <foreach collection="ids" item="id" separator="," open="(" close=")">
- #{id}
- foreach>
- select>
(2)方式二:
- select
- <include refid="Base_Column_List">include>
- from t_book where 1=1
- <foreach collection="ids" item="id" separator="," open=" and bid in (" close=")">
- #{id}
- foreach>
(3)方式三:
- select
- <include refid="Base_Column_List">include>
- from t_book where 1=1 and bid in
- (
- <foreach collection="ids" item="id" separator=",">
- #{id}
- foreach>
④:在iBookService类编写代码
- //foreach标签
- List
queryBookByForeach(BookVo bookVo);
⑤:进行 junit4单元测试
- @Test
- //foreach标签
- public void queryBookByForeach(){
- BookVo bookVo=new BookVo();
- //Arrays.asList--->将数组转换为集合
- bookVo.setIds(Arrays.asList(new Integer[]{13,17,3}));
- List
books = iBookService.queryBookByForeach(bookVo); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

choose 标签作用是通过条件判断来拼接 SQL 语句,类似于 Java 中的 switch 语句,从上到下,当有匹配的条件时,跳出 choose 语句;如果所有条件都不成立则执行 otherwise 标签中的内容,使用 choose 标签的时候,一定要注意最先需要判断的条件要放在前面,当匹配到某个条件时,就不会判断后面的语句了
语法格式:
-
1> - ...
-
-
2> - ...
-
-
3> - ...
-
- ...
-
- ...
-
①:在BookMapper类定义包含choose标签方法
- //choose 标签
- List
queryBookByChoose(Book book);
②:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByChoose" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where 1=1
- <choose>
- <when test="null!=bname and ''!=bname">
- and bname like concat('%',#{bname},'%')
- when>
- <when test="null!=btype and ''!=btype">
- and btype like concat('%',#{btype},'%')
- when>
- <otherwise>
- and bid=#{bid}
- otherwise>
- choose>
- select>
③:在iBookService类编写代码
List queryBookByChoose(Book book);
④:实现接口所定义的方法
- @Override
- public List
queryBookByChoose(Book book) { - return bookMapper.queryBookByChoose(book);
- }
⑤:进行 junit4单元测试
------测试带name类型的查询:
- @Test
- //choose 标签
- public void queryBookByChoose(){
- List
books = iBookService.queryBookByChoose(Book.builder().bname("之").build()); - books.forEach(System.out::println);
-
- }
测试结果如下:

查看sql语句:

------测试带type类型的查询:
- @Test
- //choose 标签
- public void queryBookByChoose(){
- List
books = iBookService.queryBookByChoose(Book.builder().btype("历史").build()); - books.forEach(System.out::println);
-
- }
测试结果如下:

查看sql语句:

------测试带id类型的查询:
- @Test
- //choose 标签
- public void queryBookByChoose(){
- List
books = iBookService.queryBookByChoose(Book.builder().bid(30).build()); - books.forEach(System.out::println);
-
- }
测试结果如下:

查看sql语句:

set用于更新的sql语句中,在update时,多条件更新,每个属性后面要加逗号“,”,这个时候可能会出现多一个“,”的情况,此时我们就可以使用set去掉后边的“,”修改方法,假如实体类属性为空就不修改此属性所对于的字段
①:在BookMapper类定义包含set标签方法
- //set标签
- int updateByPrimaryKeySelective(Book record);
②:在BookMapper.xml文件中进行sql语句的编写
- <update id="updateByPrimaryKeySelective" parameterType="com.zking.model.Book" >
- update t_book
- <set >
- <if test="bname != null" >
- bname = #{bname,jdbcType=VARCHAR},
- if>
- <if test="bprice != null" >
- bprice = #{bprice,jdbcType=INTEGER},
- if>
- <if test="btype != null" >
- btype = #{btype,jdbcType=VARCHAR},
- if>
- set>
- where bid = #{bid,jdbcType=INTEGER}
- update>
③:在iBookService类编写代码
int updateByPrimaryKeySelective(Book record);
④:实现接口所定义的方法
- @Override
- public int updateByPrimaryKeySelective(Book record) {
- return bookMapper.updateByPrimaryKeySelective(record
- );
- }
⑤:进行 junit4单元测试
- public void updateByPrimaryKeySelective(){
- book.setBid(27);
- book.setBname("剑与荣光");
- book.setBprice(45);
- book.setBtype("文学");
- iBookService.updateByPrimaryKeySelective(book);
- }
测试结果如下:

查看sql语句:

where标签只会在至少有一个子元素返回了SQL语句时, 才会向SQL语句中添加WHERE,并且如果WHERE之后是以AND或OR开头,会自动将其删掉。
①:在BookMapper类定义包含where标签方法
- //where标签
- List
queryBookWhere(Book book);
②:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookWhere" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book
- <where>
- <if test="bname!=null and bname!=''">
- and bname like concat('%',#{bname},'%')
- if>
- <if test="btype!=null and btype!=''">
- and btype like concat('%',#{btype},'%')
- if>
- where>
- select>
③:在iBookService类编写代码
- //where标签
- List
queryBookWhere(Book book);
④:实现接口所定义的方法
- @Override
- public List
queryBookWhere(Book book) { - return bookMapper.queryBookWhere(book);
- }
⑤:进行 junit4单元测试
------测试带name类型的查询:
- @Test
- //where标签
- public void queryBookWhere(){
- List
books = iBookService.queryBookWhere(Book.builder().bname("的").build()); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

------测试带type类型的查询:
- @Test
- //where标签
- public void queryBookWhere(){
- List
books = iBookService.queryBookWhere(Book.builder().btype("文学").build()); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

①:案例演示:Integer参数传递
(1):在BookMapper类定义方法
List queryBookByInteger(Integer bid);
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByInteger" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List">include> from t_book where 1=1
- <if test="null!=bid and ''!=bid ">
- and bid=#{bid}
- if>
- select>
(3):在iBookService类编写代码
List queryBookByInteger(Integer bid);
(4):实现接口所定义的方法
- @Override
- public List
queryBookByInteger(Integer bid) { - return bookMapper.queryBookByInteger(bid);
- }
(5):进行 junit4单元测试
---------不传递参数的测试演示(相当于查询所有)
- @Test
- public void queryBookByInteger(){
- List
books = iBookService.queryBookByInteger(null); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

ok,不带id参数的测试,通过sql语句可以看出来,相当于查询所有,那么我们再来进行带id参数的测试:
- @Test
- public void queryBookByInteger(){
- List
books = iBookService.queryBookByInteger(3); - books.forEach(System.out::println);
- }
测试结果如下:

很好,出现了bug,没有bug的程序猿,都是没有完整的程序猿人生的,我们一起来分析为什么会出现bug:
报错提示:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'bid' in 'class java.lang.Integer'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'bid' in 'class java.lang.Integer'
分析:当前的bid没有getter方法,反射异常-----传递的是一个属性,不是一个实体类,如何给它getter方法?
- <if test="null!=bid and ''!=bid ">
- and bid=#{bid}
- if>
所以,错误点在BookMapper.xml文件中的bid,如果传递的是八大基本类型,就必须使用value,value就代表当前的值
所以,将BookMapper.xml文件中的变为:
- <if test="null!=value and ''!=value ">
- and bid=#{bid}
- if>
继续测试,看效果,查看是否可以运行:

查看sql语句:

OK,nice,将xml文件在的bid全部转换为value(注意:数据库的字段除外),来继续尝试:
- <if test="null!=value and ''!=value ">
- and bid=#{value}
- if>
测试结果如下:

查看sql语句:

ok,nice~~~~nice,继续往下走~~~~··
ps:
传递Integer类型的参数,相当于传递八大基础类型
②:案例演示:String参数传递
(1):在BookMapper类定义方法
- //传递String类型的参数
- List
queryBookByString(String btype);
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByString" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where 1=1
- <if test="null!=value and ''!=value ">
- and btype=#{btype}
- if>
- select>
(3):在iBookService类编写代码
- //传递String类型的参数
- List
queryBookByString(String btype);
(4):实现接口所定义的方法
- @Override
- public List
queryBookByString(String btype) { - return bookMapper.queryBookByString(btype);
- }
(5):进行 junit4单元测试
- @Test
- //传递String类型的参数
- public void queryBookByString(){
- List
books = iBookService.queryBookByString("历史"); - books.forEach(System.out::println);
- }
测试结果如下:

报错提示:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.lang.String and [C
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.lang.String and [C
很好,又出现了bug,继续分析:
这个异常是属于参数异常的类型,不知道是什么哪里有问题,那么我们不妨大胆猜测一下,有可能是xml文件中不能使用value,改用btype尝试尝试
- <if test="null!=btype and ''!=btype ">
- and btype=#{btype}
- if>
好,继续运行,看看结果:

报错提示:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'btype' in 'class java.lang.String'
### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'btype' in 'class java.lang.String'
分析:很好,出现了bug,不过这个bug是和上面出现的bug一样,说明还是要使用value,那么我们就将所有的btype统统改为value,继续运行运行尝试尝试~~~
- <if test="null!=value and ''!=value ">
- and btype=#{value}
- if>
测试结果如下:

OK,还是在报我们第一次运行时的错误,一直在报错,这就告诉我们String类型的传参不能这么直接传参,还需要额外的参数,那么我们将BookMapper类的方法用注解的方法进行额外的设参,用@param()的方式进行设参,例如我的String类型的传递参数问题解决方案如下:
- //bookType-->参数
- //btype-->变量名
- List
queryBookByString(@Param("bookType") String btype);
mapper的映射文件如老样子,不进行修改,进行运行,看是否会报错
- <if test="null!=value and ''!=value ">
- and btype=#{value}
- if>
测试结果如下:

报错提示:
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'value' not found. Available parameters are [param1, bookType]
### Cause: org.apache.ibatis.binding.BindingException: Parameter 'value' not found. Available parameters are [param1, bookType]
好,天意难违,bug还是出现了,我们继续来分析:这里的报错显示value没有被分析,那么我们不妨可以得出是xml映射文件的sql语句中,不能使用value,要使用我们在mapper层中定义方法所用@param()方式设置的参数,来继续进行测试一波
- <if test="null!=bookType and ''!=bookType">
- and btype=#{bookType}
- if>
测试结果如下:

好,传递String类型的参数的bug终于解决掉了,当我们遇到bug时,不要放弃,要大胆尝试,从另一个方向分析出发,可能会有意外的收获
①:在BookMapper类定义方法
- List
queryBookParams(@Param("booktype") String btype, - @Param("bookid") Integer bid);
②:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookParams" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where 1=1
- <if test="null!=booktype and ''!=booktype">
- and btype=#{booktype}
- if>
- <if test="null!=bookid and ''!=bookid">
- and bid=#{bookid}
- if>
- select>
③:在iBookService类编写代码
List queryBookParams(String btype, Integer bid);
注意:方法在mapper层和service接口所定义的方法格式不一样,请认真区分并遵循
④:实现接口所定义的方法
- @Override
- public List
queryBookParams(String btype, Integer bid) { - return bookMapper.queryBookParams(btype,bid);
- }
⑤:进行 junit4单元测试
- public void queryBookParams(){
- List
books = iBookService.queryBookParams("文学", 27); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

①:在BookMapper类定义方法
List queryBookByObject(Book book);
②:在BookMapper.xml文件中进行sql语句的编写
- @Override
- public List
queryBookByObject(Book book) { - return bookMapper.queryBookByObject(book);
- }
③:在iBookService类编写代码
List queryBookByObject(Book book);
④:实现接口所定义的方法
- @Override
- public List
queryBookByObject(Book book) { - return bookMapper.queryBookByObject(book);
- }
⑤:进行 junit4单元测试
- @Test
- public void queryBookByObject(){
- List
books = iBookService.queryBookByObject(Book.builder().btype("文学").build()); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

①:在BookMapper类定义方法
List queryBookLike(Book book);
②:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookLike" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where 1=1
- <if test="null!=bname and ''!=bname">
- and bname like #{bname}
- if>
- select>
③:在iBookService类编写代码
- //模糊查询
- List
queryBookLike(Book book);
④:实现接口所定义的方法
- @Override
- public List
queryBookLike(Book book) { - return bookMapper.queryBookLike(book);
- }
重点:相当于占位符,参数传递时需要手动拼接%%百分号 例如:"zs"-->'zs' 会自动拼接单引号
⑤:进行 junit4单元测试
方式一:使用${}方式进行模糊查询
- @Test
- //模糊查询
- public void queryBookLike(){
- List
books = iBookService.queryBookLike(Book.builder().bname("%与%").build()); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

重点:使用$传递参数时,只会传递参数本身--->例如:"zs"-->zs 不会自动拼接单引号
⑤:进行 junit4单元测试
方式二:使用#{}方式进行模糊查询
- @Test
- //模糊查询
- public void queryBookLike(){
- List
books = iBookService.queryBookLike(Book.builder().bname("与").build()); - books.forEach(System.out::println);
- }
测试结果如下:
- <if test="null!=bname and ''!=bname">
- and bname like '%${bname}%'
- if>

查看sql语句:

⑤:进行 junit4单元测试
方式三:使用concat()方式进行模糊查询
- <if test="null!=bname and ''!=bname">
- and bname like concat('%',#{bname},'%')
- if>
测试结果如下:

查看sql语句:

答:参数类型为字符串,#会在前后加单引号['],$则直接插入值
数据库要执行 SQL 访问数据,数据库是个执行机构,它只会检查传来的 SQL 是不是合乎语法,而并不会关心这个语句是否会造成伤害(数据泄露或破坏)。正因为只要符合语法规则就会执行的机制,导致 SQL 有了注入的风险。
SQL 本身就是个字符串,而且一般没有加密,字符串可能被黑客劫持修改,这样就可能造成数据库执行了不该执行的动作。
SQL 注入的惯用做法是通过把 SQL 子串插入到 Web 表单项或页面请求(Url)的查询字符串中提交,最终达到欺骗服务器执行恶意操作的目的。
常见案例包括通过植入 SQL 骗过登录验证。而之前很多影视网站泄露 VIP 会员密码的事件,很多就是通过 SQL 植入到 WEB 表单暴露的,并且这类表单特别容易受到攻击。通过 SQL 植入,不仅可以非法获取账号信息,严重的还能够篡改、删除重要数据信息。
返回结果集的类型:
(1):在BookMapper类定义方法
List queryBookByResultMap();
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByResultMap" resultMap="BaseResultMap">
- /*有参构造方法*/
- select <include refid="Base_Column_List"/> from t_book
- select>
(3):在iBookService类编写代码
List queryBookByResultMap();
(4):实现接口所定义的方法
- @Override
- public List
queryBookLike(Book book) { - return bookMapper.queryBookLike(book);
- }
(5):进行 junit4单元测试
- @Test
- //查询返回结果集
- //resultMap:适合使用返回值是自定义实体类的情况
- //resultType:适合使用返回值的数据类型是非自定义的,即jdk的提供的类型
- public void queryBookByResultMap(){
- List
books = iBookService.queryBookByResultMap(); - books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

(1):在BookMapper类定义方法
Book querySingleBookById(Integer bid);
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="querySingleBookById" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where bid=#{bid}
- select>
(3):在iBookService类编写代码
Book querySingleBookById(Integer bid);
(4):实现接口所定义的方法
- @Override
- public Book querySingleBookById(Integer bid) {
- return bookMapper.querySingleBookById(bid);
- }
(5):进行 junit4单元测试
- @Test
- //使用resultType返回单个对象
- public void querySingleBookById(){
- Book book = iBookService.querySingleBookById(13);
- System.out.println(book);
- }
测试结果如下:

查看sql语句:

(1):在BookMapper类定义方法
Map querySingleBookByMap(Integer bid);
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="querySingleBookByMap" resultType="java.util.Map">
- select <include refid="Base_Column_List"/> from t_book where bid=#{bid}
- select>
(3):在iBookService类编写代码
Map querySingleBookByMap(Integer bid);
(4):实现接口所定义的方法
- @Override
- public Map
querySingleBookByMap(Integer bid) { - return bookMapper.querySingleBookByMap(bid);
- }
(5):进行 junit4单元测试
- @Test
- public void querySingleBookByMap(){
- Map
book1 = iBookService.querySingleBookByMap(13); - System.out.println(book1);
- }
测试结果如下:

查看sql语句:

(1):在BookMapper类定义方法
List
(2):在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookByMaps" resultType="java.util.Map">
- select <include refid="Base_Column_List"/> from t_book
- select>
(3):在iBookService类编写代码
List
(4):实现接口所定义的方法
- @Override
- public List
- return bookMapper.queryBookByMaps();
- }
(5):进行 junit4单元测试
- @Test
- //List
- public void queryBookByMaps(){
- List
- System.out.println(maps);
-
- }
测试结果如下:

查看sql语句:

实现分页查询的步骤:
- <dependency>
- <groupId>com.github.pagehelpergroupId>
- <artifactId>pagehelperartifactId>
- <version>5.1.2version>
- dependency>
例如:我的pom.xml文件
-
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0modelVersion>
-
- <groupId>com.zkinggroupId>
- <artifactId>mybatis01artifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>warpackaging>
-
- <name>mybatis01 Maven Webappname>
-
- <url>http://www.example.comurl>
-
- <properties>
- <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
- <maven.compiler.source>1.8maven.compiler.source>
- <maven.compiler.target>1.8maven.compiler.target>
-
- <junit.version>4.13junit.version>
-
- <servlet.version>4.0.1servlet.version>
-
- <mybatis.version>3.4.5mybatis.version>
-
- <mysql.version>5.1.44mysql.version>
-
- <log4j2.version>2.9.1log4j2.version>
-
- <lombok.version>1.18.24lombok.version>
- properties>
- <dependencies>
-
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>${junit.version}version>
- <scope>testscope>
- dependency>
-
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>javax.servlet-apiartifactId>
- <version>${servlet.version}version>
- <scope>providedscope>
- dependency>
-
- <dependency>
- <groupId>org.mybatisgroupId>
- <artifactId>mybatisartifactId>
- <version>${mybatis.version}version>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>${mysql.version}version>
- dependency>
-
-
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-coreartifactId>
- <version>${log4j2.version}version>
- dependency>
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-apiartifactId>
- <version>${log4j2.version}version>
- dependency>
-
- <dependency>
- <groupId>org.apache.logging.log4jgroupId>
- <artifactId>log4j-webartifactId>
- <version>${log4j2.version}version>
- dependency>
-
- <dependency>
- <groupId>org.projectlombokgroupId>
- <artifactId>lombokartifactId>
- <version>${lombok.version}version>
- <scope>providedscope>
- dependency>
-
- <dependency>
- <groupId>com.github.pagehelpergroupId>
- <artifactId>pagehelperartifactId>
- <version>5.1.2version>
- dependency>
- dependencies>
-
- <build>
- <finalName>mybatis01finalName>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.pluginsgroupId>
- <artifactId>maven-compiler-pluginartifactId>
- <version>3.7.0version>
- <configuration>
- <source>${maven.compiler.source}source>
- <target>${maven.compiler.target}target>
- <encoding>${project.build.sourceEncoding}encoding>
- configuration>
- plugin>
-
-
- <plugin>
- <groupId>org.mybatis.generatorgroupId>
- <artifactId>mybatis-generator-maven-pluginartifactId>
- <version>1.3.2version>
- <dependencies>
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>${mysql.version}version>
- dependency>
- dependencies>
- <configuration>
- <overwrite>trueoverwrite>
- configuration>
- plugin>
- plugins>
- build>
- project>
-
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
- plugin>
例如:我的mybatis.cfg..xml文件
- configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
- <configuration>
-
- <properties resource="jdbc.properties"/>
-
-
- <settings>
-
- <setting name="logImpl" value="LOG4J2"/>
- settings>
-
-
-
-
-
- <plugins>
-
- <plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
- plugins>
-
-
-
- <environments default="development">
- <environment id="development">
-
- <transactionManager type="jdbc"/>
-
-
-
-
-
-
- <dataSource type="POOLED">
- <property name="driver"
- value="${jdbc.driver}"/>
- <property name="url"
- value="${jdbc.url}"/>
- <property name="username" value="${jdbc.username}"/>
- <property name="password" value="${jdbc.password}"/>
- dataSource>
- environment>
- environments>
-
- <mappers>
- <mapper resource="com/zking/mapper/BookMapper.xml"/>
- mappers>
- configuration>
- package com.zking.util;
-
- import java.io.Serializable;
- import java.util.Map;
-
- import javax.servlet.http.HttpServletRequest;
-
- public class PageBean implements Serializable {
-
- private static final long serialVersionUID = 2422581023658455731L;
-
- //页码
- private int page=1;
- //每页显示记录数
- private int rows=10;
- //总记录数
- private int total=0;
- //是否分页
- private boolean isPagination=true;
- //上一次的请求路径
- private String url;
- //获取所有的请求参数
- private Map
map; -
- public PageBean() {
- super();
- }
-
- //设置请求参数
- public void setRequest(HttpServletRequest req) {
- String page=req.getParameter("page");
- String rows=req.getParameter("rows");
- String pagination=req.getParameter("pagination");
- this.setPage(page);
- this.setRows(rows);
- this.setPagination(pagination);
- this.url=req.getContextPath()+req.getServletPath();
- this.map=req.getParameterMap();
- }
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public Map
getMap() { - return map;
- }
-
- public void setMap(Map
map) { - this.map = map;
- }
-
- public int getPage() {
- return page;
- }
-
- public void setPage(int page) {
- this.page = page;
- }
-
- public void setPage(String page) {
- if(null!=page&&!"".equals(page.trim()))
- this.page = Integer.parseInt(page);
- }
-
- public int getRows() {
- return rows;
- }
-
- public void setRows(int rows) {
- this.rows = rows;
- }
-
- public void setRows(String rows) {
- if(null!=rows&&!"".equals(rows.trim()))
- this.rows = Integer.parseInt(rows);
- }
-
- public int getTotal() {
- return total;
- }
-
- public void setTotal(int total) {
- this.total = total;
- }
-
- public void setTotal(String total) {
- this.total = Integer.parseInt(total);
- }
-
- public boolean isPagination() {
- return isPagination;
- }
-
- public void setPagination(boolean isPagination) {
- this.isPagination = isPagination;
- }
-
- public void setPagination(String isPagination) {
- if(null!=isPagination&&!"".equals(isPagination.trim()))
- this.isPagination = Boolean.parseBoolean(isPagination);
- }
-
- /**
- * 获取分页起始标记位置
- * @return
- */
- public int getStartIndex() {
- //(当前页码-1)*显示记录数
- return (this.getPage()-1)*this.rows;
- }
-
- /**
- * 末页
- * @return
- */
- public int getMaxPage() {
- int totalpage=this.total/this.rows;
- if(this.total%this.rows!=0)
- totalpage++;
- return totalpage;
- }
-
- /**
- * 下一页
- * @return
- */
- public int getNextPage() {
- int nextPage=this.page+1;
- if(this.page>=this.getMaxPage())
- nextPage=this.getMaxPage();
- return nextPage;
- }
-
- /**
- * 上一页
- * @return
- */
- public int getPreivousPage() {
- int previousPage=this.page-1;
- if(previousPage<1)
- previousPage=1;
- return previousPage;
- }
-
- @Override
- public String toString() {
- return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", isPagination=" + isPagination
- + "]";
- }
- }
- //分页查询
- List
queryBookPager(Book book, PageBean pageBean);
- @Override
- public List<Book> queryBookPager(Book book, PageBean pageBean) {
- return bookMapper.queryBookPager(book);
- }
- //分页查询
- List
queryBookPager(Book book, PageBean pageBean);
- @Override
- public List
queryBookPager(Book book, PageBean pageBean) { - return bookMapper.queryBookPager(book);
- }
- //设置分页处理
- if (null != pageBean && pageBean.isPaginate()) {
- PageHelper.startPage(pageBean.getCurPage(), pageBean.getPageRecord());
- }
①:使用插件后,查询实际返回的是Page
- Page
page = (Page)list; - System.out.println("页码:" + page.getPageNum());
- System.out.println("页大小:" + page.getPageSize());
- System.out.println("总记录:" + page.getTotal());
②:使用PageInfo
- PageInfo pageInfo = new PageInfo(list);
- System.out.println("页码:" + pageInfo.getPageNum());
- System.out.println("页大小:" + pageInfo.getPageSize());
- System.out.println("总记录:" + pageInfo.getTotal());
我的分页获取信息,使用第二种方式:
- @Test
- //分页查询
- public void queryBookPager(){
- PageBean pageBean=new PageBean();
- //判断是否分页
- if(null!=pageBean&&pageBean.isPagination())
- //pageBean.getPage()---当前页数
- //pageBean.getRows()----每页条数
- PageHelper.startPage(pageBean.getPage(),pageBean.getRows());
- List
bookList = iBookService.queryBookPager(Book.builder().build(), pageBean); - System.out.println(bookList.getClass());
-
- if(null!=pageBean&&pageBean.isPagination()) {
- PageInfo pageInfo = new PageInfo(bookList);
- System.out.println("页码:" + pageInfo.getPageNum());
- System.out.println("页大小:" + pageInfo.getPageSize());
- System.out.println("总记录:" + pageInfo.getTotal());
- List list = pageInfo.getList();
- list.forEach(System.out::println);
- }
- }
测试结果如下:

查看sql语句:

| > | > |
| < | < |
| & | & |
| 空格 |  ; |
问题:为什么需要转义?
答:因为在mybatis中的sql语句是写在xml文件中的,但是在处理范围查询的时候经常要用到<,>,$等特殊字符
①:定义一个特殊类,用来存放范围值
- package com.zking.vo;
-
- import com.zking.model.Book;
- import lombok.Data;
-
- import java.util.List;
-
- /**
- * @author 唐渊
- * @create 2022-07-23 9:26
- */
- @Data //getter/setter/toString
- public class BookVo extends Book {
- //最小价格
- private Integer min;
- //最大价格
- private Integer max;
-
-
-
- }
②:在BookMapper类定义方法
- //范围查询,转义字符处理
- List
queryBookRange(BookVo bookVo);
③:在BookMapper.xml文件中进行sql语句的编写
- <select id="queryBookRange" resultType="com.zking.model.Book">
- select <include refid="Base_Column_List"/> from t_book where 1=1
- <if test="null!=min and ''!=min">
- and bprice>#{min}
- if>
- <if test="null!=max and ''!=max">
- and bprice<#{max}
- if>
- select>
④:在iBookService类编写代码
- //范围查询,转义字符处理
- List
queryBookRange(BookVo bookVo);
⑤:实现接口所定义的方法
- @Override
- public List
queryBookRange(BookVo bookVo) { - return bookMapper.queryBookRange(bookVo);
- }
⑥:进行 junit4单元测试
- @Test
- //范围查询,转义字符处理
- public void queryBookRange(){
- BookVo bookVo=new BookVo();
- bookVo.setMin(50);
- bookVo.setMax(200);
- List
books = iBookService.queryBookRange(bookVo); - //不使用转义字符前
- //元素内容必须由格式正确的字符数据或标记组成。
- books.forEach(System.out::println);
- }
测试结果如下:

查看sql语句:

mybatis原则上是不能够一次批量执行多条SQL语句,比如新增、删除、更新等,但是修改jdbc url连接带参数可以实现相同效果
- spring:
- datasource:
- username: root
- password: mysql
- # allowMultiQueries 是否允许一条SQL语句包含多个执行SQL以分号;分隔
- url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC&allowMultiQueries=true
- driver-class-name: com.mysql.cj.jdbc.Driver
allowMultiQueries=true 允许一条SQL语句包含多个执行SQL以分号;分隔,是必须添加的
①:在BookMapper类定义方法
- //批量新增
- int insertBatch(List
list) ;
②:在BookMapper.xml文件中进行sql语句的编写
- <insert id="insertBatch">
- insert into t_book ( bname,bprice,btype ) values
- <foreach collection="list" separator="," item="it">
- (#{it.bname},#{it.bprice},#{it.btype})
- foreach>
- insert>
③:在iBookService类编写代码
- //批量新增
- int insertBatch(List
list) ;
④:实现接口所定义的方法
- @Override
- public int insertBatch(List
list) { - return bookMapper.insertBatch(list);
- }
⑤:进行 junit4单元测试
- @Test
- //批量新增
- public void insertBatch(){
- List
list = new ArrayList<>(); - book.setBname("西罗马帝国");
- book.setBprice(34);
- book.setBtype("历史");
- list.add(book);
- book.setBname("世界大战一");
- book.setBprice(65);
- book.setBtype("历史");
- list.add(book);
- int i = iBookService.insertBatch(list);
- if (i>0) {
- System.out.println("yes");
- }
-
- }
测试结果如下:

查看sql语句:

八:批量更新
①:在BookMapper类定义方法
- //批量更新
- int updateForNew(List
List) ;
②:在BookMapper.xml文件中进行sql语句的编写
- <update id="updateForNew">
- insert into t_book (bname,bprice,btype) values
- <foreach collection="list" separator="," item="it">
- (#{it.bname},#{it.bprice},#{it.btype})
- foreach>
- on duplicate key update bname=values(bname);
- update>
③:在iBookService类编写代码
- @Override
- int updateForNew(List
List) ; -
-
④:实现接口所定义的方法
- @Override
- public int updateForNew(List
list) { - return bookMapper.insertBatch(list);
- }
⑤:进行 junit4单元测试
- @Test
- //批量更新
- public void updateForNew(){
- List
list = new ArrayList(); - book.setBname("上帝之鞭");
- book.setBprice(56);
- book.setBtype("历史");
- list.add(book);
- book.setBname("西楚霸王");
- book.setBprice(77);
- book.setBtype("历史");
- list.add(book);
- int i = iBookService.updateForNew(list);
- if (i>0) {
- System.out.println("yes");
- }
- }
测试结果如下:

九:批量删除
①:在BookMapper类定义方法
- //批量删除
- int deleteBatch(List
idList) ;
②:在BookMapper.xml文件中进行sql语句的编写
- <delete id="deleteBatch">
- delete from t_book where bid in
- <foreach collection="list" item="it" separator="," open="(" close=")">
- #{it}
- foreach>
- delete>
③:在iBookService类编写代码
- //批量删除
- int deleteBatch(List
idList) ;
④:实现接口所定义的方法
- @Override
- public int deleteBatch(List
idList) { - return bookMapper.deleteBatch(idList);
- }
⑤:进行 junit4单元测试
- @Test
- //批量删除
- public void deleteBatch(){
- List
list = new ArrayList<>(); - list.add(31);
- list.add(32);
- int i = iBookService.deleteBatch(list);
- if (i>0) {
- System.out.println("yes");
- }
-
- }
测试结果如下:

查看sql语句:

代码操作有点多,但全是干货
