MyBatis入门知识点

    科技2026-01-19  11

    Mybatis入门知识点

    一、MyBatis介绍1.什么是mybatis2.mybatis的体系结构3.mybatis的应用4.Mybatis框架5.实现分页 二、MyBatis实现增删查改功能1.maven环境搭建2.创建连接3.dao层里的方法4.main方法里的调用5.多条件查询使用map集合6.当JavaBean属性与列表字段不一致时解决的映射问题7.真分页查询(1).使用Map实现真分页(二).使用JavaBean实现真分页 8.假分页查询9.真分页和假分页的区别10.插入数据时的主键回显 三、Mybatis的动态SQL1.介绍2.常用元素(1)、判断元素:if choose(2)、 关键字元素: trim where set(3)、循环元素:foreach 四、Mybatis框架的关联映射1.介绍2.实现形式(1)、嵌套查询:(2)、嵌套结果查询:(3)、使用实体类存储: 五、集合映射1、介绍2、实现方式(1)、嵌套查询(2)、嵌套结果 六、映射器1、介绍2.实现

    一、MyBatis介绍

    1.什么是mybatis

    mybatis封装了几乎所有的jdbc代码和参数的手工设置以及结果集的检索,支持普通的SQL查询、存储过程和高级映射,是一款优秀的持久层框架,使用简单的xml或Java注解做配置和定义映射关系,将Java中的pojos映射成数据库中的记录。实体类–》数据库中的表实体类中的属性—》表中的字段实体类的对象----》表中的记录

    2.mybatis的体系结构

    1.配置加载

    xml配置Java代码注解mybatis将sql的配置信息加载成为一个个的mapped Statement的对象(包含了传入的参数映射配置、执行的SQL语句、结果映射配置)并将 其存储到内存中

    SQL解析

    当api接口层接受到调用时,会接受到传入的SQL的id和传入对象(可以是map/JavaBean或者基本数据类型),mybatis根据id找到对应的mapped Statement对象,并且根据传入的参数对其进行解析,解析后可以得到最终要执行的SQL语句和参数

    SQL执行

    把解析出的SQL语句和参数拿到数据库执行,得到操作数据库的结果

    结果映射

    将操作数据库的结果按照映射的配置进行转换(可以转换hashmap/JavaBean或基本数据类型),并将最终结果返回

    3.mybatis的应用

    1、主配置文件:指定数据库的连接信息以及设置框架的相关参数。

    2、关联映射文件:用于定义SQL语句及相关映射信息。

    4.Mybatis框架

    ​ SqlSessionFactoryBuilder:负责加载配置文件,同时创建SqlSessionFactoryBuilder实例​ SqlSessionFactory:每一个Mybatis的应用程序都以一个SqlSessionFactory对象为核心,该对象负责创建SqlSessionFactorySqlSession:该对象包含了所有执行SQL操作的方法,用于执行已映射的SQL语句

    5.实现分页

    在使用SqlSession的selectList()方法时,指定一个分页参数器 RowBounds;

    分页参数器的构造器RowBounds(offset,pageSize);

    Offset: 抓取记录的起始位置;

    pageSize: 指定的每页显示的记录数;

    二、MyBatis实现增删查改功能

    1.maven环境搭建

    创建maven项目完成后,配置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.0</modelVersion> <groupId>com.qst</groupId> <artifactId>mybatisMaven</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> </dependencies> <!-- 配置 maven 项目的jdk版本 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>

    添加相关配置文件

    把文件mybatis-config.xml放在src/main/resouces下面

    把文件EmpMapper.xml放在你所用的实体类下面

    - 修改mybatis-config.xml

    - 使用EmpMapper.xml

    2.创建连接

    public class MyUtil { static SqlSessionFactory sf =null; static { //1.定义mybatis-config的文件地址 String conf = "mybatis-config.xml"; Reader read; try { read = Resources.getResourceAsReader(conf);//Resources读取配置文件 SqlSessionFactoryBuilder sfb = new SqlSessionFactoryBuilder();//加载配置文件 sf = sfb.build(read); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static SqlSession getSqlSession(){ return sf.openSession();//返回SQL session对象 } }

    3.dao层里的方法

    package com.qst.dao; import java.util.List; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.session.SqlSession; import com.qst.pojo.Emp; import com.qst.util.MyUtil; public class EmpDao { //员工信息添加 public void insertEmp(Emp emp){ SqlSession session=MyUtil.getSqlSession();//用于执行已经映射的SQL语句 session.insert("addEmp",emp); session.commit();//提交 session.close();//记得关闭,以免造成资源的浪费 } //更新员工信息 public void updateEmp(Emp emp){ SqlSession session=MyUtil.getSqlSession(); session.update("updateEmp",emp); session.commit(); System.out.println("成功"); session.close(); } //根据id查询员工信息 public Emp findEmpById(int id){ SqlSession session=MyUtil.getSqlSession(); Emp emp=session.selectOne("selectEmpById",id); session.close(); return emp; } //查询所有员工列表信息 public List<Emp> findEmps(){ SqlSession session=MyUtil.getSqlSession(); List<Emp> emps=session.selectList("findAll"); session.close(); return emps; } //分页 public List<Emp> findEmps1(int page,int pageSize){ SqlSession session=MyUtil.getSqlSession(); RowBounds rb=new RowBounds((page-1)*pageSize,pageSize); List<Emp>emps=session.selectList("findAll2",null,rb); session.close(); return emps; } //根据id删除员工信息 public void deleEmp(int id){ SqlSession session=MyUtil.getSqlSession(); session.delete("delEmpById", id); session.commit(); System.out.println("删除成功"); session.close(); } }

    4.main方法里的调用

    package com.qst.test; import java.util.List; import com.qst.dao.EmpDao; import com.qst.pojo.Emp; public class Test { public static void main(String[] args) { //Emp emp = new Emp(); /*emp.setName("上帝"); emp.setSex("男"); emp.setSalary(50000.0); emp.setAddress("中山市德创智谷");*/ //emp.setName("神仙"); EmpDao dao = new EmpDao(); //dao.insertEmp(emp); // Emp emp=dao.findEmpById(12); // System.out.println(emp); // emp.setName("美女"); // emp.setSex("女"); // dao.updateEmp(emp); // List<Emp>emps=dao.findEmps1(2, 2); // System.out.println(emps); dao.deleEmp(12); } }

    5.多条件查询使用map集合

    parameterType的类型为"map" <select id="findEmpByNameAndSalary" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp where name=#{name} and salary=#{salary} </select>

    dao方法

    public List<Emp> findEmpByNAndS(Map map){ SqlSession session=MyUtil.getSqlSession(); List<Emp>emps=session.selectList("findEmpByNameAndSalary", map); session.close(); return emps; }

    主方法

    Map map=new HashMap(); map.put("name","文琴麻麻" ); map.put("salary", 10000); List<Emp> emps=dao.findEmpByNAndS(map); System.out.println(emps);

    6.当JavaBean属性与列表字段不一致时解决的映射问题

    Mapper.xml

    使用resultMap解决 <mapper namespace="/"> <!-- 根据id查找对应的员工信息 --> <select id="selectEmpId" parameterType="int" resultMap="empMap"> select * from t_emp where id=#{id} </select> <resultMap type="com.qst.pojo.Emp2" id="empMap"> <result property="addr" column="address"/> </resultMap> </mapper>

    dao方法

    public Emp2 findEmp(int id){ SqlSession session=MyUtil.getSqlSession(); Emp2 emp=session.selectOne("selectEmpId", id); session.close(); return emp; }

    测试结果

    //JavaBean属性与字段不一致的映射 EmpDao2 ed=new EmpDao2(); Emp2 emp2=ed.findEmp(3); System.out.println(emp2);

    7.真分页查询

    (1).使用Map实现真分页

    Mapper.xml

    <!-- 真分页实现员工信息列表查询 --> <select id="findPages" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp limit #{offset},#{pageSize} </select>

    dao

    //真分页查询 public List<Emp> findPages(int page,int pageSize){ SqlSession session=MyUtil.getSqlSession(); Map map=new HashMap(); map.put("offset",(page-1)*pageSize); map.put("pageSize", pageSize); List<Emp>emps=session.selectList("findPages", map); return emps; }

    测试

    //真分页 List<Emp>emps=dao.findPages(1, 2); System.out.println(emps);
    (二).使用JavaBean实现真分页
    创建empbean类

    Mapper.xml

    <!-- 使用JavaBean实现分页 --> <select id="findPages" parameterType="com.qst.pojo.EmpBean" resultType="com.qst.pojo.Emp"> select * from t_emp limit #{offset},#{pageSize} </select>

    dao

    //使用JavaBean实现真分页 public List<Emp> findPages(int page,int pageSize){ SqlSession session=DBUtil.getSqlSession(); EmpBean eb=new EmpBean(); eb.setPage(page); eb.setPageSize(pageSize); List<Emp>emps=session.selectList("findPages", eb); return emps; }

    测试

    List<Emp>emps=ed.findPages(3, 2); System.out.println(emps);

    8.假分页查询

    Mapper.xml

    <!-- 假分页 --> <select id="findAll2" resultType="com.qst.pojo.Emp"> select * from t_emp </select>

    dao

    //假分页 public List<Emp> findEmps1(int page,int pageSize){ SqlSession session=MyUtil.getSqlSession(); RowBounds rb=new RowBounds((page-1)*pageSize,pageSize); List<Emp>emps=session.selectList("findAll2",null,rb); session.close(); return emps; }

    main

    //假分页 List<Emp>emps=dao.findEmps1(2, 2); System.out.println(emps);

    9.真分页和假分页的区别

    真分页:查询的SQL语句,确定要显示的数量和内容,然后每次都去数据库取出该少量数据假分页:一次性取出所有的数据,然后再显示 使用分页参数器 RowBounds;,分页参数器的构造器RowBounds(offset,pageSize);

    10.插入数据时的主键回显

    Mapper.xml

    useGeneratedKeys:是否要主键回显keyProperty:要回显的主键 <!-- 员工信息添加,主键的回显 --> <insert id="addEmpInfo" parameterType="com.qst.pojo.Emp" keyProperty="id" useGeneratedKeys="true"> insert into t_emp(name,sex,salary,address)values(#{name},#{sex},#{salary},#{address}) </insert>

    dao

    //插入员工信息,主键回显 public void addEmpInfo(Emp emp){ SqlSession session=MyUtil.getSqlSession(); session.insert("addEmpInfo", emp); session.commit(); session.close(); }

    测试

    emp.setName("唐漂亮"); emp.setSex("女"); emp.setSalary(10000); emp.setAddress("湖南"); dao.addEmpInfo(emp); System.out.println("获取到回显的id="+emp.getId());

    三、Mybatis的动态SQL

    1.介绍

    动态SQL是MySQL框架强大的特性之一,在一些组合查询页面,需要根据用户输入的条件生成不同的查询SQL,这在jdbc中需要在代码中拼写SQL,但在Mybatis中可以解决这个问题使用动态SQL元素与jstl相似,它允许我们在xml中去构建不同的SQL语句

    2.常用元素

    (1)、判断元素:if choose

    if元素:是简单的条件判断逻辑,满足条件时追加if元素内的SQL,不满足条件时不追加

    <select id="askEmp" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp where 1=1 <if test="name!=null and name!=''"> and name=#{name} </if> <!-- ps:使用and连接 --> <if test="address!=null and address!=''"> and address=#{address} </if> </select> //if元素的应用 public List<Emp> askEmp(String name,String address){ SqlSession session=MyUtil.getSqlSession(); Map map=new HashMap(); map.put("name", name); map.put("address", address); List<Emp> emps=session.selectList("askEmp", map); session.close(); return emps; } public static void main(String[] args) { Emp emp = new Emp(); EmpDao dao = new EmpDao(); List<Emp> emps=dao.askEmp3("丁丁", ""); System.out.println(emps); }

    choose元素:类似if else语句

    <!--choose的应用 --> <select id="askEmp2" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp <choose> <when test="name!=null and name!=''"> where name=#{name} </when> <when test="address!=null and address!=''"> where address=#{address} </when> <otherwise> where salary>1000 </otherwise> </choose> //choose元素的应用 public List<Emp> askEmp2(String name,String address){ SqlSession session=MyUtil.getSqlSession(); Map map=new HashMap(); map.put("name", name); map.put("address", address); List<Emp> emps=session.selectList("askEmp2", map); return emps; }
    (2)、 关键字元素: trim where set

    trim元素

    可以在自己包含的内容前面加上某些前缀,也可以在其后加上某些后缀,与之对应属性prefix和suffix

    可以把包含内容的某些首部过滤掉也就是忽略,也可以把包含内容的某些尾部过滤掉,对应设置属性prefixOverrides和suffix Overrides

    <!-- trim元素的where应用 --> <select id="askEmp3" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp <trim prefix="where" prefixOverrides="and|or"> <if test="name!=null and name!=''"> and name=#{name} </if> <!-- ps:使用and连接 --> <if test="address!=null and address!=''"> and address=#{address} </if> </trim> </select> //trim元素应用,dao里面的方法 public List<Emp> askEmp3(String name,String address){ SqlSession session=MyUtil.getSqlSession(); Map map=new HashMap(); map.put("name", name); map.put("address", address); List<Emp> emps=session.selectList("askEmp3", map); return emps; } <!-- trim元素的set应用 --> <update id="askEmp_set" parameterType="com.qst.pojo.Emp" > update t_emp <trim prefix="set" suffixOverrides=","> <if test="name!=null and name!=''"> name=#{name}, </if> <if test="address!=null and address!=''"> address=#{address} </if> </trim> where id=#{id} </update> //trim元素的set应用 public void changeEmp(Emp emp){ SqlSession session=MyUtil.getSqlSession(); session.update("askEmp_set", emp); session.commit(); session.close(); }

    where元素

    <!-- where元素应用 --> <select id="whereEmp" parameterType="map" resultType="com.qst.pojo.Emp"> select * from t_emp <where> <if test="name!=null and name!=''"> name=#{name} </if> <if test="address!=null and address!=''"> and address=#{address} </if> </where> </select> //where元素的应用,dao里面的方法 public List<Emp> whereEmp(String name,String address){ SqlSession session=MyUtil.getSqlSession(); Map map=new HashMap(); map.put("name", name); map.put("address", address); List<Emp> emps=session.selectList("whereEmp", map); return emps; }

    set元素

    <!-- set元素的应用 --> <update id="setEmp" parameterType="com.qst.pojo.Emp"> update t_emp <set> <if test="name!=null and name!=''"> name=#{name}, </if> <if test="address!=null and address!=''"> address=#{address} </if> </set> where id=#{id} </update> //set元素的应用 public void changeEmp2(Emp emp){ SqlSession session=MyUtil.getSqlSession(); session.update("setEmp", emp); session.commit(); session.close(); }
    (3)、循环元素:foreach

    foreach实现了循环逻辑,可以进行一个集合迭代,主要用于构建in条件中

    <!-- foreach元素的使用,批量查询 --> <select id="foreachEmp" parameterType="com.qst.pojo.Emp" resultType="com.qst.pojo.Emp"> select * from t_emp where id in <foreach collection="arr" item="arr" open="(" separator="," close=")"> #{arr} </foreach> </select> <!-- foreach元素的使用,批量删除 --> <delete id="forEmpDel" parameterType="com.qst.pojo.Emp" > delete from t_emp where id in <foreach collection="arr" item="arr" open="(" separator="," close=")"> #{arr} </foreach> </delete> //foreach批量查询 public List<Emp> foreachEmp(int[] arrs) { SqlSession session=MyUtil.getSqlSession(); Emp e=new Emp(); e.setArr(arrs); List<Emp> emp=session.selectList("foreachEmp",e); session.close(); return emp; } //foreach批量删除 public void forEmpDel(int[] arrs){ SqlSession session=MyUtil.getSqlSession(); Emp e=new Emp(); e.setArr(arrs); session.delete("forEmpDel",e); session.commit(); System.out.println("删除成功"); session.close(); } public static void main(String[] args) { Emp emp = new Emp(); EmpDao dao = new EmpDao(); //foreach批量查询 int arr[]={2,4,7}; List<Emp> emps=dao.foreachEmp(arr); System.out.println(emps);*/ //foreach批量删除 int arrs[]={2,16,17}; dao.forEmpDel(arrs); }

    四、Mybatis框架的关联映射

    1.介绍

    在查询时经常需要两个或者两个以上关联表的数据,通过关联映射可以由一个对象获取关联对象的数据。例如查询一个emp对象,可以通过关联映射获取员工所在部门的dept对象信息

    2.实现形式

    (1)、嵌套查询:
    通过执行另外的一个SQL语句来返回关联数据结果(查两次) <!-- 关联映射之多对一应用嵌套查询 --> <select id="joinEmp" parameterType="int" resultMap="empJoin"> select * from t_emp where id=#{id} </select> <resultMap type="com.qst.pojo.Emp" id="empJoin"> <!-- property:关联属性名在Emp类里面的dept javaType:关联的类型 column:关联的数据库字段,外键--> <association property="dept" javaType="com.qst.pojo.Dept" column="dept_id" select="askDeptId"> </association> </resultMap> <select id="askDeptId" parameterType="int" resultType="com.qst.pojo.Dept"> select * from t_dept where id=#{dept_id} </select> //多对一关联映射嵌套查询 public Emp findEmpJoinById(int id){ SqlSession session=MyUtil.getSqlSession(); Emp emp=session.selectOne("joinEmp", id); return emp; } public static void main(String[] args) { Emp emp = new Emp(); EmpDao dao = new EmpDao(); //关联映射嵌套查询 emp=dao.findEmpJoinById(15); System.out.println(emp); }
    (2)、嵌套结果查询:
    <!-- 关联映射多对一应用之嵌套结果 --> <select id="joinEmp2" parameterType="int" resultMap="empJoin2"> select e.id,e.name,e.sex,e.salary,e.address,d.id as d_id,d.name as d_name from t_emp as e join t_dept as d on e.dept_id=d.id where e.id=#{id} </select> <resultMap type="com.qst.pojo.Emp" id="empJoin2"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="sex" column="sex"/> <result property="salary" column="salary"/> <result property="address" column="address"/> <association property="dept" javaType="com.qst.pojo.Dept" column="dept_id"> <id property="id" column="d_id"/> <result property="name" column="d_name" /> </association> </resultMap>

    //多对一关联映射嵌套结果 public Emp findEmpJoinById2(int id){ SqlSession session=MyUtil.getSqlSession(); Emp emp=session.selectOne("joinEmp2", id); return emp; } public static void main(String[] args) { Emp emp = new Emp(); EmpDao dao = new EmpDao(); //关联映射嵌套查询 emp=dao.findEmpJoinById2(1); System.out.println(emp); }
    (3)、使用实体类存储:
    <!-- 关联映射多对一应用之使用实体类存储 ps:记得取别名,当两张表重名时!--> <select id="joinEmp3" parameterType="int" resultType="com.qst.pojo.Ed"> select e.id ,e.name,e.sex,e.salary,e.address,d.name as deptName from t_emp e,t_dept d where e.dept_id=d.id and e.id=#{id} </select> //多对一关联映射pojo存储 public Ed findEmpJoinById3(int id){ SqlSession session=MyUtil.getSqlSession(); Ed ed=session.selectOne("joinEmp3", id); return ed; } public static void main(String[] args) { Ed ed = new Ed(); EmpDao dao = new EmpDao(); //关联映射嵌套查询 ed=dao.findEmpJoinById2(1); System.out.println(ed); } package com.qst.pojo; //创建一个实体类来存储 public class Ed { private Integer id; private String name; private String sex; private Double salary; private String address; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } private String deptName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } @Override public String toString() { return "Ed [id=" + id + ", name=" + name + ", sex=" + sex + ", salary=" + salary + ", address=" + address + ", deptName=" + deptName + "]"; } }

    五、集合映射

    1、介绍

    当查询某个表的记录信息时。如果关联表有多条相关记录,此时就可以使用集合映射,例如:查询某个部门的对象信息,通过集合映射可以获取该部门中的所有员工对象信息

    2、实现方式

    (1)、嵌套查询
    private List<Emp> emps;//首先在Dept类中添加集合类型 <!-- 一对多关系映射之嵌套查询 --> <select id="askDept" parameterType="int" resultMap="deptMap"> select * from t_dept where id=#{id} </select> <resultMap type="com.qst.pojo.Dept" id="deptMap"> <id property="id" column="id" /> <result property="name" column="name" /> <collection property="emps" column="id" javaType="java.util.List" ofType="com.qst.pojo.Emp" select="findEmpBy"> </collection> </resultMap> <select id="findEmpBy" parameterType="int" resultType="com.qst.pojo.Emp"> select * from t_emp where dept_id=#{id} </select> //一对多嵌套查询 public Dept findDeptById(int id) { SqlSession session = MyUtil.getSqlSession(); Dept dept = session.selectOne("askDept", id); session.close(); return dept; }
    (2)、嵌套结果
    <select id="askDept2" parameterType="int" resultMap="deptMap1"> select d.id,d.name,e.id as e_id,e.name as e_name,e.sex,e.salary,e.address from t_dept d,t_emp e where d.id=e.dept_id and d.id=#{id} </select> <resultMap type="com.qst.pojo.Dept" id="deptMap1"> <id property="id" column="id" /> <result property="name" column="name" /> <collection property="emps" javaType="java.util.List" ofType="com.qst.pojo.Emp"> <id property="id" column="e_id" /> <result property="name" column="e_name" /> <result property="sex" column="sex" /> <result property="salary" column="salary" /> <result property="address" column="address" /> </collection> </resultMap> //一对多嵌套结果 public Dept findDeptById2(int id) { SqlSession session = MyUtil.getSqlSession(); Dept dept = session.selectOne("askDept2", id); session.close(); return dept; } public static void main(String[] args) { DeptDao dd=new DeptDao(); Dept dept=new Dept(); dept=dd.findDeptById2(2); System.out.println(dept); }

    六、映射器

    1、介绍
    映射器是MyBatis中最核心的组件之一,而从MyBatis 3开始,还支持接口映射非常简洁;映射器主要是在MyBatis和Spring框架整合集成时使用。
    2.实现

    (1)、创建接口

    public interface EmpMapper { public List<Emp> findAll();//该方法名和mapper.xml的id名称必须一致 }

    (2)、获取映射对象

    public class MapperFactory { public static EmpMapper getEmpMapper(){ SqlSession session=MyUtil.getSqlSession(); //获取映射器对象 EmpMapper mapper=session.getMapper(EmpMapper.class); return mapper; } }

    (3)、测试

    ps:进行测试之前,要记得把namespace里的路径改成你创建的接口路径

    <mapper namespace="com.qst.dao.EmpMapper"> public class Test1 { public static void main(String[] args) { EmpMapper em=MapperFactory.getEmpMapper(); List<Emp> emps=em.findAll(); System.out.println(emps); } }
    Processed: 0.016, SQL: 9