Springboot集成Mybatis和Mybatis常用知识点总结

1、Springboot整合mybatis

1.1导入mybatis整合依赖

<!--   mybatis整合     -->
        <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>

<!-- lombok     -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

1.2连接完数据库就去applicaton.yml配置一下数据库

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

1.3编写与数据库对应的实体类

package com.example.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data  //生成get、set方法
@AllArgsConstructor //生成所有参数构造器
@NoArgsConstructor //生成无参构造器
public class User {
    private Integer id;
    private String name;
    private String pwd;

}

1.4.编写mapper

package com.example.mapper;

import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface UserMapper {
    //查询用户的全部信息
    List<User> getUserList();

    //select 找出id=1的用户
    User getUserById(int id);

    //insert 增加一个用户
    int insertUser(User user);

    //delete 删除id=4的用户
    int deleteUser(int id);

    //update 将id=2的用户名字改为小龙
    int updateUser(User user);

}

@maper注解

@Mapper是mybatis自身带的注解。在spring程序中,mybatis需要找到对应的mapper,在编译时生成动态代理类,与数据库进行交互,这时需要用到@Mapper注解

1.5.编写mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.mapper.UserMapper">
    <select id="getUserList" resultType="user">
        select *
        from mybatis.user
    </select>

    <select id="getUserById" resultType="user" parameterType="int">
        select *
        from mybatis.user
        where id = #{id};
    </select>

    <insert id="insertUser" parameterType="user">
        insert into mybatis.user (id, name, pwd)
        values (#{id}, #{name}, #{pwd});
    </insert>

    <delete id="deleteUser" parameterType="int">
        delete
        from mybatis.user
        where id = #{id};
    </delete>

    <update id="updateUser" parameterType="user">
        update mybatis.user
        set name = #{name},
            pwd = #{pwd}
        where id = #{id};
    </update>

</mapper>

这里我们用了别名而且我们把这个mapper.xml文件放在了resources目录下,所以我们要去application.yml配置一下

mybatis:
  type-aliases-package: com.example.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml

1.6编写controller

package com.example.controller;

import com.example.mapper.UserMapper;
import com.example.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @GetMapping("/getUserList")
    public List<User> getUserList(){
        return userMapper.getUserList();
    }

    @GetMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id") int id){
        return userMapper.getUserById(id);
    }

    @GetMapping("/insertUser")
    public String insertUser(){
        userMapper.insertUser(new User(5,"xiaoming","111"));
        return "ok";
    }

    @GetMapping("/deleteUser")
    public String deleteUser(){
        userMapper.deleteUser(5);
        return "ok";
    }

    @GetMapping("/updateUser")
    public String updateUser(){
        userMapper.updateUser(new User(5,"xx","111"));
        return "ok";
    }

}

Mybatis常用知识点

1:自动生成主键
\1) 若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上

<insert id="insertEmployee" 	parameterType="com.mybatis.beans.Employee"  
			databaseId="mysql"
			useGeneratedKeys="true"
			keyProperty="id">
		insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
</insert>

2:参数传递的种方法
\1) 单个普通类型参数
​ 可以接受基本类型,包装类型,字符串类型等。这种情况MyBatis可直接使用这个参数,不需要经过任何处理。
直接使用#{参数名称},直接取就可以了
\2) 多个参数

任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,或者0,1…,值就是参数的值
mapper中

List<Employee> selectByGenderAndAge(Short gender,String age );

xml中错误的参数传递

<select id="selectByGenderAndAge" resultMap="BaseResultMap" >
  select * from employee where gender = #{gender} and age = #{age}
</select>

注意这里按参数名去引用的话会报如下错误,mybatis错误提示很细致,这里明确给我们提示,匿名参数只能使用arg1, arg0, param1, param2 类似的形式这种传参方式的缺点是不够灵活,必须严格按照参数顺序来引用

<!--BindingException: Parameter 'gender' not found. Available parameters are [arg1, arg0, param1, param2]-->
<!--所以正确的引用方式如下-->
 <select id="selectByGenderAndAge" resultMap="BaseResultMap" >
    select *  from employee where gender = #{param1} and age = #{param2}
  </select>

\3) 命名参数

为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是我们自己指定的名字
mapper

List<Employee> selectByGenderAndAge( @Param("gender") Shortgender,@Param("age") String age );

xml中


<select id="selectByGenderAndAge" resultMap="BaseResultMap" >
  select * from employee where gender = #{gender} and age = #{age}
</select>

\4) POJO

当这些参数属于我们业务POJO时,我们直接传递POJO
mapper

List <Employee> selectByBeans(Employee employee);

xml

<select id="selectByBeans" resultMap="BaseResultMap" parameterType="com.Employee">
  select
  *
  from employee where gender = #{gender} and age = #{age}
</select>

\5) Map

我们也可以封装多个参数为map,直接传递
mapper

List<Employee> selectByMapParams(Map params);
<select id="selectByMapParams" resultMap="BaseResultMap" parameterType="map">
  select * from employee where gender = #{gender} and age = #{age}
</select>

\6) Collection/Array
mapper

List <Employee> findByList(List list);
<select id="findByList" resultMap="BaseResultMap" >
SELECT * from employee where age in
    <foreach collection="list" open="(" separator="," close=")" item="age">
      #{age}
    </foreach>
  </select>

7:直接使用JSON传递参数
mapper

List <Employee> findByJSONObject(JSONObject params);
<select id="findByJSONObject" resultMap="BaseResultMap" parameterType="com.alibaba.fastjson.JSONObject">
  select
  *
  from employee where gender = #{gender} and age = #{age}
</select>

8:.参数类型为对象+集合

@Data
public class Department {
    private Long id;

    private String deptName;

    private String descr;

    private Date createTime;

    List<Employee> employees;

}

mapper

List <Employee> findByDepartment(@Param("department")Department department);

xml

<select id="findByDepartment" resultMap="BaseResultMap" parameterType="com.wg.demo.po.Department">
    SELECT * from employee where dept_id =#{department.id} and age in
    <foreach collection="department.employees" open="(" separator="," close=")" item="employee">
        #{employee.age}
    </foreach>
</select>

3${}与#{}的区别

3.1、符号类型

(1)#{}:参数占位符,即预编译
(2)${} :字符串替换符,即SQL拼接

3.2、防注入问题

(1)#{}:很大程度上能防止sql 注入
(2)${}:不能防止sql 注入
1)#{}:将传入的数据都当成一个字符串,会对传入的变量自动加一个单引号。如:user_id = #{userId},如果传入的值是111,那么解析成sql时的值为user_id = ‘111’,如果传入的值是id,则解析成的sql为user_id = ‘id’。

(2)${}:将传入的参数直接显示生成在sql中,且不加任何引号。如:user_id = ${userId},如果传入的值是111,那么解析成sql时的值为user_id = 111 , 如果传入的值是id,则解析成的sql为user_id = id
3.2、用$的情况

在某些特殊场合下只能用${},不能用#{}。例如:在使用排序时ORDER BY ${id}, 如果使用#{id},则会被解析成ORDER BY “id”,这显然是一种错误的写法。
2) 方 式 一 般 用 于 传 入 数 据 库 对 象 , 例 如 传 入 表 名 用 {}方式一般用于传入数据库对象,例如传入表名 用 会快一些。

Select  *  from  ${tableName}  where  user_id = #{userId}

4resultMap自定义映射

resultMap中的属性定义
\1) 自定义resultMap,实现高级结果集映射

\2) id :用于完成主键值的映射

\3) result :用于完成普通列的映射

\4) association :一个复杂的类型关联;许多结果将包成这种类型

\5) collection : 复杂类型的集
在这里插入图片描述

<select id="getEmployeeById" resultMap="myEmp">
	select id, last_name,email, gender from tbl_employee where id =#{id}
</select>
<resultMap type="com.mybatis.beans.Employee" id="myEmp">
		<id column="id"  property="id" />
		<result column="last_name" property="lastName"/>
		<result column="email" property="email"/>
		<result column="gender" property="gender"/>
</resultMap>
Association

1)POJO中的属性可能会是一个对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用association标签定义对象的封装规则

public class Department {
	private Integer id ; 
	private String departmentName ;
//  省略 get/set方法
}
public class Employee {
	private Integer id ; 
	private String lastName; 
	private String email ;
	private String gender ;
	private Department dept ;
    // 省略 get/set方法
}

xml

<resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDept">
		<id column="eid" property="id"/>
		<result column="last_name" property="lastName"/>
		<result column="email" property="email"/>
		<result column="gender" property="gender"/>
		<association property="dept" javaType="com.atguigu.mybatis.beans.Department">
			<id column="did" property="id"/>
			<result column="dept_name" property="departmentName"/>
		</association>
</resultMap>
<resultMap type="com.mybatis.beans.Employee" id="myEmpAndDept">
		<id column="eid" property="id"/>
		<result column="last_name" property="lastName"/>
		<result column="email" property="email"/>
		<result column="gender" property="gender"/>
		<association property="dept" javaType="com.mybatis.beans.Department">
			<id column="did" property="id"/>
			<result column="dept_name" property="departmentName"/>
		</association>
</resultMap>
collection

1)OJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用collection标签定义对象的封装规则

public class Department {
	private Integer id ; 
	private String departmentName ;
	private List<Employee> emps ;
}

XML

<select id="getDeptAndEmpsById" resultMap="myDeptAndEmps">
		SELECT d.id did, d.dept_name ,e.id eid ,e.last_name ,e.email,e.gender 
		FROM tbl_dept d  LEFT OUTER JOIN tbl_employee e ON  d.id = e.d_id 
		WHERE d.id = #{id}
	</select>
	<resultMap type="com.mybatis.beans.Department" id="myDeptAndEmps">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
		<!-- 
			property: 关联的属性名
			ofType: 集合中元素的类型
		 -->
		<collection property="emps"  ofType="com.mybatis.beans.Employee">
			<id column="eid" property="id"/>
			<result column="last_name" property="lastName"/>
			<result column="email" property="email"/>
			<result column="gender" property="gender"/>
		</collection>
</resultMap>

拓展
javaType和ofType的区别
javaType用来指定对象所属的java数据类型,也就是private List<Employee>Employees 的ArrayList类型,用在association
ofType用来指定对象的所属javaBean类,也就是尖括号的泛型private List<Employee>Employees,用在collection

5MyBatis动态SQL

if where

\1) If用于完成简单的判断.

Where用于解决SQL语句中where关键字以及条件中第一个and或者or的问题

<select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.beans.Employee">
		select id , last_name ,email  , gender  
		from tbl_employee 
		<where>
			<if test="id!=null">
				and id = #{id}
			</if>
			<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
				and last_name = #{lastName}
			</if>
			<if test="email!=null and email.trim()!=''">
				and email = #{email}
			</if>
			<if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
				and gender = #{gender}
			</if>
		</where>
</select>
trim

\1) Trim 可以在条件判断完的SQL语句前后添加或者去掉指定的字符

prefix: 添加前缀

prefixOverrides: 去掉前缀

suffix: 添加后缀

suffixOverrides: 去掉后缀

select id="/、getEmpsByConditionTrim" resultType="com.atguigu.mybatis.beans.Employee">
		select id , last_name ,email  , gender  
		from tbl_employee 
		<trim prefix="where"  suffixOverrides="and">
			<if test="id!=null">
				 id = #{id} and
			</if>
			<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
				 last_name = #{lastName} and
			</if>
			<if test="email!=null and email.trim()!=''">
				 email = #{email} and
			</if>
			<if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
				gender = #{gender}
			</if>
		</trim>
</select>
set

\1) set 主要是用于解决修改操作中SQL语句中可能多出逗号的问题

<update id="updateEmpByConditionSet">
		update  tbl_employee  
		<set>
			<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
				 last_name = #{lastName},
			</if>
			<if test="email!=null and email.trim()!=''">
				 email = #{email} ,
			</if>
			<if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
				gender = #{gender} 
			</if>
		</set>
		 where id =#{id}
	</update>
choose

choose 主要是用于分支判断,类似于java中的switch case,只会满足所有分支中的一个

<select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.beans.Employee">
		select id ,last_name, email,gender from tbl_employee
		<where>
			<choose>
				<when test="id!=null">
					id = #{id}
				</when>
				<when test="lastName!=null">
					last_name = #{lastName}
				</when>
				<when test="email!=null">
					email = #{email}
				</when>
				<otherwise>
					 gender = 'm'
				</otherwise>
			</choose>
		</where>
</select>
foreach

\1) foreach 主要用于循环迭代

collection: 要迭代的集合

item: 当前从集合中迭代出的元素

open: 开始字符

close:结束字符

separator: 元素与元素之间的分隔符

index:

​ 迭代的是List集合: index表示的当前元素的下标

​ 迭代的Map集合: index表示的当前元素的key

<select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.beans.Employee">
		 select id , last_name, email ,gender from tbl_employee where  id in 
		 <foreach collection="ids" item="curr_id" open="(" close=")" separator="," >
		 		#{curr_id}
		 </foreach>
</select>
sql

\1) sql 标签是用于抽取可重用的sql片段,将相同的,使用频繁的SQL片段抽取出来,单独定义,方便多次引用.

\2) 抽取SQL:

<sql id="selectSQL">
		select id , last_name, email ,gender from tbl_employee
</sql>

引用SQL:

<include refid="selectSQL"></include>
扩展-PageHelper分页插件

\1) 导入相关包pagehelper-x.x.x.jar 和 jsqlparser-0.9.5.jar

\2) 在MyBatis全局配置文件中配置分页插件

<plugins>
	<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

\3) 使用PageHelper提供的方法进行分页

可以使用更强大的PageInfo封装返回结果

Page对象的使用

\1) 在查询之前通过PageHelper.startPage(页码,条数)设置分页信息,该方法返回Page对象

@Test
	public void testPageHelper()  throws Exception{
		SqlSessionFactory ssf = getSqlSessionFactory();
		SqlSession session = ssf.openSession();
		try {
			EmployeeMapper mapper = 
                      session.getMapper(EmployeeMapper.class);
			//设置分页信息
			Page<Object> page = PageHelper.startPage(9, 1);
			List<Employee> emps = mapper.getAllEmps();
			for (Employee employee : emps) {
				System.out.println(employee);
			}
			System.out.println("=============获取分页相关的信息=================");
			System.out.println("当前页: " + page.getPageNum());
			System.out.println("总页码: " + page.getPages());
			System.out.println("总条数: " + page.getTotal());
			System.out.println("每页显示的条数: " + page.getPageSize());
		} finally {
			session.close();
		}
	}

原理

首先是在Mybatis里面配置了分页拦截器(PageInterceptor),即在执行相关Sql之前会拦截做一点事情;

这里通过setLocalPage()方法,将分页信息保存在当前线程中。查询方法与之处于同一个线程中,共享ThreadLocal中的数据。

selectlist查询之后赋值给的List list。这个list是Page 类型。

再将list放到PageInfo<>中即可。

\1) 在查询完数据后,使用PageInfo对象封装查询结果,可以获取更详细的分页信息以及

可以完成分页逻辑


@Test
	public void testPageHelper1()  throws Exception{
		SqlSessionFactory ssf = getSqlSessionFactory();
		SqlSession session = ssf.openSession();
		try {
			EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);
			//设置分页信息
			Page<Object> page = PageHelper.startPage(9, 1);
			List<Employee> emps = mapper.getAllEmps();
			// 
			PageInfo<Employee> info  = new PageInfo<>(emps,5);
			for (Employee employee : emps) {
				System.out.println(employee);
			}
			System.out.println("=============获取详细分页相关的信息=================");
			System.out.println("当前页: " + info.getPageNum());
			System.out.println("总页码: " + info.getPages());
			System.out.println("总条数: " + info.getTotal());
			System.out.println("每页显示的条数: " + info.getPageSize());
			System.out.println("是否是第一页: " + info.isIsFirstPage());
			System.out.println("是否是最后一页: " + info.isIsLastPage());
			System.out.println("是否有上一页: " + info.isHasPreviousPage());
			System.out.println("是否有下一页: " + info.isHasNextPage());
			
			System.out.println("============分页逻辑===============");
			int [] nums = info.getNavigatepageNums();
			for (int i : nums) {
				System.out.print(i +" " );
			}
		} finally {
			session.close();
		}
	}

PageInfo包含的信息

private int pageNum;//当前页码
 private int pageSize;//设置每页多少条数据
private int size;//当前页有多少条数据
private int startRow;//当前页码第一条数据的
private int endRow;//当前页码的开始条
private int pages;//当前页码结束条
private int prePage;//上一页(页面链接使用)
private int nextPage;//下一页(页面链接使用)
private boolean isFirstPage;//是否为第一页
private boolean isLastPage;//是否为最后一页
private boolean hasPreviousPage;//是否有前一页
private boolean hasNextPage;//是否有下一页
private int navigatePages;//导航页码数(就是总共有多少页)
private int[] navigatepageNums;//导航页码数(就是总共有多少页),可以用来遍历
private int navigateFirstPage;//首页号
private int navigateLastPage;//尾页号

Springboot 集成pagehelper

<dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper-spring-boot-starter</artifactId>
      <version>1.2.13</version>
  </dependency>

配置文件

pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql

pagehelper配置参数参考

补充,mybatis中转译字符
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值