MyBatis基础

MyBatis

第一章 框架的概述

1.1 三层架构

  1. mvc:web开发中,使用mvc架构模式。m:数据,v:视图,c:控制器
    • c控制器:接收数据,调用service对象,显示请求的处理结果。当前使用servlet作为控制器
    • v视图:现在使用jsp、html、css、js。显示请求的处理结果,把m中的数据显示出来
    • m数据:来自数据库mysql,来自文件,来自网络
  2. mvc的作用:
    1. 实现解耦合
    2. 让mvc各负其责
    3. 使得系统扩展更好,更容易维护
  3. 三层架构:
    1. 界面层(视图层):接收用户的请求,调用service,显示请求的处理结果。包含了jsp、html、servlet等对象。对应的包controller。
    2. 业务逻辑层:处理业务逻辑,使用算法处理数据的。把数据返回给界面层。对应的是service包,和包中的很多的XXXService类。例如:StudentService、OrderService、ShopService等等。
    3. 持久层(数据访问层):访问数据库,或者读取文件,访问网络,获取数据。对应的包是dao。和包中很多的XXXDao类。例如:StudentDao、OrderDao、ShopDao等等。

1.2 三层架构请求的处理流程

  • 用户发起请求----->界面层----->业务逻辑层----->持久层----->数据库(mysql)

1.3 为什么要使用三层架构?

  1. 结构清晰、耦合度低、各层分工明确
  2. 可维护性高,可扩展性高
  3. 有利于标准化
  4. 开发人员可以只关注整个结构中的其中某一层功能实现
  5. 有利于各层逻辑的复用

1.4 三层架构模式和框架

  • 每一层对应着一个框架
    1. 界面层—SpringMVC框架
    2. 业务逻辑层—Spring框架
    3. 持久层—MyBatis框架

1.5 框架

  • 什么是框架(framework)
    • 框架:就是一个软件,完成了部分的功能。软件中的类和类之间的方法调用都已经规定好了。通过这些可以完成某些功能。框架看做是模板
    • 框架是可以升级的、改造的。框架是安全的
    • 框架是对某一个方面有用的,不是全能的

1.6 框架解决的问题

  1. 框架能实现技术的整合
  2. 提供开发的效率,降低难度

1.7 JDBC访问数据库的优缺点

  • 优点:
    1. 直观,好理解
  • 缺点:
    1. 创建很多对象Connection、Statement、ResultSet
    2. 注册驱动
    3. 执行sql语句
    4. 把ResultSet转为Student,List集合
    5. 关闭资源
    6. sql语句和业务逻辑层代码混在一起

1.8 MyBatis框架

  • MyBatis:是一个持久层框架,原名是ibatis,2010年改名为MyBatis,MyBatis可以操作数据库,对数据执行增删改查。看做是高级的jdbc,用来解决jdbc的缺点。

  • MyBatis能做什么?

    1. 注册驱动
    2. 创建jdbc中使用的Connection、Statement、ResultSet
    3. 执行sql语句,得到ResultSet
    4. 处理ResultSet,把记录集中的数据转为java对象,同时还能把java对象放入到List集合
    5. 关闭资源
    6. 实现sql语句和java代码的解耦合
  • MyBatis官网:https://mybatis.org/mybatis-3/zh/index.html

  • MyBatis下载jar包或在Maven设置依赖:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qjn9yqyF-1627139123993)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210712200509562.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wfsDj6ws-1627139124001)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210712200741130.png)]

第二章 MyBatis入门

2.1 第一个例子

  • 实现步骤:

    1. 创建student表(id,name,email,age)
    DROP DATABASE IF EXISTS springdb;
    CREATE DATABASE IF NOT EXISTS springdb;
    USE springdb;
    
    CREATE TABLE student(
    	id INT PRIMARY KEY AUTO_INCREMENT,#编号
    	`name` VARCHAR(80) NOT NULL,#姓名
    	email VARCHAR(80) NOT NULL,#电子邮件
    	age INT NOT NULL#年龄
    );#学生表
    
    1. 新建maven项目

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CbYOU0I9-1627139124005)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210717151846175.png)]

    1. 修改pom.xml
      1. 加入依赖mybatis依赖、mysql驱动、junit
      2. 在加入资源插件
    <?xml version="1.0" encoding="UTF-8"?>
    
    <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.kgc</groupId>
      <artifactId>ch01-first</artifactId>
      <version>1.0</version>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
      <!--依赖列表-->
      <dependencies>
        <!--mybatis依赖-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.1</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.9</version>
        </dependency>
        <!--单元测试-->
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <!--资源插件:处理src/main/java目录下的xml-->
        <resources>
          <resource>
            <directory>src/main/java</directory>
            <includes>
              <include>**/*.properties</include>
              <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
          </resource>
        </resources>
    
      </build>
    </project>
    
    
    1. 创建实体类Student。定义属性,属性名和列名保持一致
    /**
     * 学生类
     */
    public class Student {
        //属性名和列名一样
        private Integer id;
        private String name;
        private String email;
        private Integer age;
    
        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 getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "学生实体的信息{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", email='" + email + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    1. 创建Dao接口,定义操作数据库的方法
    /**
     * 实现类数据访问层接口
     */
    public interface StudentDao {
        //查询一个学生
        Student getStudentById(Integer id);
    }
    
    
    1. 创建xml文件(mapper文件),写sql语句
      • mybatis框架推荐是把sql语句和java代码分开
      • mapper文件:定义和Dao接口在同一目录,一个表一个mapper文件
    <?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.kgc.dao.StudentDao">
        <!--查询一个学生student
            <select>:表示查询操作,里面是select语句
            id:要执行的sql语句的唯一标识,是一个自定义字符串
            推荐使用dao接口中的方法名称
            resultType:告诉mybatis,执行sql语句,把数据复制给那个类型的java对象
            resultType的值现在使用的java对象的全限定名称
            #{id}:占位符,表示从java程序中传入过来的数据
        -->
        <select id="getStudentById" resultType="com.kgc.pojo.Student">
            select * from student where id = #{id}
        </select>
    </mapper>
    
    <!--
      1.约束文件
        http://mybatis.org/dtd/mybatis-3-mapper.dtd
        约束文件的作用:定义和限制当前文件中可以使用的标签和属性,以及标签出现的顺序。
      2.mapper是根标签
        namespace:命名空间,必须有值,不能为空。唯一值
                    推荐使用Dao接口的全限定名称。
        作用:参与识别生气了语句的作用
      3.在mapper里面可以写 insert、update、delete、select等标签
      <insert>:里面是insert语句,表示执行的insert操作
      <update>:里面是update语句
      <delete>:里面是delete语句
      <select>:里面是select语句
    -->
    
    1. 创建mybatis的主配置文件(xml文件):有一个,放在recources目录下
      1. 定义创建连接实例的数据源(DateSource)对象
      2. 指定其他mapper文件的位置
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <!--配置数据源:创建Connection对象-->
                <dataSource type="POOLED">
                    <!--driver:驱动的内容-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <!--连接数据库的url-->
                    <property name="url" value="jdbc:mysql://localhost:3306/springdb?useUnicode=true&amp;
                    characterEncoding=utf-8"/>
                    <!--用户名-->
                    <property name="username" value="root"/>
                    <!--密码-->
                    <property name="password" value="ok"/>
                </dataSource>
            </environment>
        </environments>
        <!--指定其他mapper文件的位置
            指定其他mapper文件的目的是找到其他文件的sql语句
        -->
        <mappers>
            <!--
                使用mapper的resources属性指定mapper文件的路径
                这个路径是从target/classes路径开始的
                使用注意:
                resource="mapper文件的路径使用‘/’分割路径"
                一个mapper 的resource指定一个mapper文件
            -->
            <mapper resource="com/kgc/dao/StudentDao.xml"/>
        </mappers>
    </configuration>
    
    1. 创建测试的内容
      • 使用main方法,测试mybatis访问数据库
      • 也可以使用junit访问数据库
    public class MyTest {
        //测试mybatis执行sql语句
        @Test
        public void testSelectStudentById() throws IOException {
            //调用mybatis某个对象的方法,执行mapper文件中的sql语句
            //mybatis核心类:SqlSessionFactory
            //1. 定义mybatis主配置文件的位置,从类路径开始的相对路径
            String config = "config.xml";
            //2. 读取主配置文件。使用mybatis框架中的Resources类
            InputStream is = Resources.getResourceAsStream(config);
            //3. 创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder类
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //4. 获取SqlSession对象
            SqlSession session = factory.openSession();
            //5. 指定要执行的sql语句的id
            // sql的id = namespace+"."+select|update|insert|delete标签的id属性值
            String sqlId = "com.kgc.dao.StudentDao"+"."+"getStudentById";
            //6. 通过SqlSession方法,执行sql语句
            Student student = session.selectOne(sqlId,1002);
            System.out.println("使用mybatis查询一个学生="+student);
            //7. 关闭SqlSession对象
            session.close();
        }
    }
    

2.2 概念

  1. 自动提交:当你的sql语句执行完毕后,提交事务。数据库更新操作之间保存到数据
  2. 手动(手工)提交事务:在你需要提交事务的位置,执行方法,提交事务或者回顾事务

2.3 MyBatis的一些重要对象

  1. Resources:mybatis框架中的对象,一个作用读取主配置文件
InputStream is = Resources.getResourceAsStream("config.xml");
  1. SqlSessionFactoryBuilder:负责创建SqlSessionFactory对象
 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
  1. SqlSessionFactory(重要对象)
    • SqlSessionFactory是重量级的对象,创建此对象需要使用更多的资源和时间。在项目中有一个就可以了
    • SqlSessionFactory接口:作用是SqlSession的工厂,就是创建SqlSession对象
    • DefaultSqlSessionFactory是实现类
public class DefaultSqlSessionFactory implements SqlSessionFactory{  }
  • SqlSessionFactory接口中的方法
    1. openSession():获取一个默认的SqlSession对象,默认是需要手工提交事务的
    2. openSession(boolean):boolean参数表示是否自动提交事务
      • true:创建一个自动提交事务的SqlSession对象
      • false:等同于没有参数的openSession
  1. SqlSession对象
    • SqlSession对象是通过SqlSessionFactory获取的。SqlSession本身是接口
    • DefaultSqlSession实现类
public class DefaultSqlSession implements SqlSession{  }
  • SqlSession作用是提供了大量的执行sql语句的方法:
selectOne:执行sql语句,最多得到一行记录,超过一行会报错
selectList:执行sql语句,返回多行数据
selectMap:执行sql语句,得到一个Map结果
insert:执行insert语句
update:执行update语句
delete:执行delete语句
commit:提交事务
rollback:回顾事务
  • 注意:SqlSession对象不是线程安全的,使用的步骤:
    1. 在方法的内部,执行sql语句之前,先获取SqlSession对象
    2. 调用SqlSession的方法,执行sql语句
    3. 关闭SqlSession对象,执行SqlSession.close()

2.4 使用工具类和模板

  1. 创建模板,mapper文件模板和mybatis主配置文件模板
    • 创建模板的步骤:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCxev2qp-1627139124013)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210718223251800.png)]

  • 创建模板文件:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bquRSHKT-1627139124016)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210718223600007.png)]

  • 创建文件选择使用的模板:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ksoyIpX-1627139124021)(C:\Users\naizhi\AppData\Roaming\Typora\typora-user-images\image-20210718224320149.png)]

  • 工具类的创建
/**
 * 工具类:创建SqlSession对象
 */
public class MyBatisUtil {
    private static SqlSessionFactory factory = null;

    static {
        String config = "mybatis.xml";
        try {
            InputStream is = Resources.getResourceAsStream(config);
            factory = new SqlSessionFactoryBuilder().build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //创建方法,获取SqlSession对象
    public static SqlSession getSqlSession() {
        SqlSession session = null;
        if (factory!=null){
            session = factory.openSession();//openSession(true)
        }
        return session;
    }

    //关闭SqlSession对象
    public static void close(SqlSession session) {
        if (null != session) {
            session.close();
        }
    }
}
  • 使用工具类
@Test
    public void testInsertById() throws IOException {
        //1. 获取SqlSession
        SqlSession session = MyBatisUtil.getSqlSession();
        //2. 指定sqlId
        String sqlId = "com.kgc.dao.StudentDao.getStudentById";
        //3. 执行SqlSession的方法,表示执行sql语句
        Student student = session.selectOne(sqlId, 1001);
        System.out.println(student);
        //4. 关闭SqlSession对象
        MyBatisUtil.close(session);
    }

第三章 MyBatis的dao代理

3.1 dao代理

  • mybatis提供代理:mybatis创建Dao接口的实现类对象,完成对sql语句的执行。mybatis创建一个对象代替你的dao实现类功能
  • 使用mybatis代理的要求
    1. mapper文件中的namespace一定是dao接口的全限定名称
    2. mapper文件中标签的id是dao接口方法名称
  • mybatis代理实现方式:
    • 使用SqlSession对象的方法getMapper(dao.class)
    • 例如:现在的StudentDao接口
SqlSession session = MyBatisUtil.getSqlSession();
StudentDao dao = session.getMapper(StudentDao.class);//等同于StudentDao dao = n
Student student = dao.selectById(1001);
  • mybatis-dao的使用
@Test
    public void testInsertById() throws IOException {
        //1. 获取SqlSession
        SqlSession session = MyBatisUtil.getSqlSession();
        //2. 获取dao的代理
        StudentDao dao = session.getMapper(StudentDao.class);
        Student student = dao.selectById(1001);
        System.out.println(student);
        //3. 关闭SqlSession对象
        MyBatisUtil.close(session);
    }

3.2 理解参数

  • 理解参数:通过Java程序把数据传入到mapper文件中的sql语句。参数主要是指dao接口方法的形参
3.2.1 parameterType
  • parameterType:表示参数的类型,指定dao方法的形参数据类型。这个形参的数据类型是给mybatis使用,mybatis在给sql语句的参数赋值时使用。PreparedStatement.set(位置,值)

  • 使用方式:

    <!--
        parameterType:指定dap接口的形参类型,
                       这个属性的值可以使用java类型的全限定名称或者mybatis定义的别名
        mybatis执行的sql语句:select * from student where id = ?
        ?是占位符,使用jdbc中的PreparedStatement执行这样的sql语句
        PreparedStatement pst = com.PreparedStatement(sql);
        给?赋值
        参数是Integer,执行pst.setInt(1,1001)
        参数是String,执行pst.setString(1,"1001")
	第一种用法:java类型的全限定类型名称,parameterType="java.lang.Integer"
	第二种用法:mybatis定义的java类型的别名parameterType="int"
	parameterType:mybatis通过反射机制可以获取,dao接口方法参数的类型,可以不写
    -->
    <select id="getStudentById" parameterType="int"
            resultType="com.kgc.pojo.Student">
        select * from student where id = #{id}
    </select>
3.2.2 dao接口方法有一个简单类型的参数
//dao接口的方法形参是一个简单类型的
//简单类型:java基本数据类型和String
Student selectByEmail(String email);
<!--
	dao接口是一个简单类型的参数
	mapper文件,获取这个参数值,使用#{任意字符}
-->
<select id="getStudentById" resultType="com.kgc.pojo.Student">
    select * from student where email=#{e}
</select>
3.2.3 dao接口方法有多个简单类型的参数
  • @Param:命名参数,在方法的形参前面使用的,定义参数名,这个名称可以用在mapper文件中

  • dao接口中的方法的定义:

/*
  多个简单类型的参数
  使用@Param命名参数,注解是mybatis提供的
  位置:在形参定义的前面
  属性:value=自定义的参数名称,value可以省略
*/
List<Student> selectByNameOrAge(@Param(value="name") String name,
                                @Param("age") Integer age);
  • mapper文件:
<!--
 	多个简单类型的参数
	当使用@Param命名后,例如@Param("name")
	在mapper中,使用#{命名的参数},例如#{name}
-->
<select id="selectByNameOrAge" resultType="com.kgc.pojo.Student">
    select * from student where name =#{name} or age = #{age}
</select>
3.2.4 dao接口方法使用一个对象作为参数
  • 方法的形参是一个java对象,这个java对象表示多个参数。使用对象的属性值作为参数使用
  • java对象:
public class Student {
    private Integer id;
    private String name;
    private String email;
    private Integer age;
    //set|get方法
}
public class QueryParam {
    private Object p1;
    private Object p2;
    //set|get方法
}
  • dao接口中的方法定义:
/*
   一个java对象作为参数(对象由属性,每个属性有sat,get方法)
*/
List<Student> selectByObject(Student student);

List<Student> selectByQueryParam(QueryParam param);
  • mapper文件:
<!--
    一个java对象作为方法的参数,使用对象的属性作为参数值使用
    简单的语法:#{属性名},mybatis调用此属性的getXXX()方法获取属性值
-->
<select id="selectByObject" resultType="com.kgc.pojo.Student">
    select * from student where name=#{name} or age=#{age}
</select>
<select id="selectByQueryParam" resultType="com.kgc.pojo.Student">
    select * from student where name=#{p1} or age=#{p2}
</select>
<!--复杂的语法格式:#{属性名,javaType=java类型的全限定名称,jdbcType=mysql中定义列的数据类型}-->
<select id="selectByObject" resultType="com.kgc.pojo.Student">
    select * from student where 
    name=#{name,javaType=java.lang.String,jdbcType=varchar} 
    or
    age=#{age,javaType=java.lang.Integer,jdbcType=integer}
</select>
3.2.5 dao接口中多个简单类型的参数,使用位置
  • 参数位置:dao接口中方法的形参列表,从左往右,参数的位置是0,1,2……

  • 语法格式:#{arg0},#{arg1}

  • dao接口中的方法定义:

/*
  使用位置,获取参数
*/
List<Student> selectByNameOrAge( String name,Integer age);
  • mapper文件:
<!--
	mybatis版本是3.5.1
 	使用位置获取参数值,到接口方法是多个简单类型的参数
	语法:#{arg0},#{arg1}……
-->
<select id="selectByNameOrAge" resultType="com.kgc.pojo.Student">
    select * from student where name =#{arg0} or age = #{arg1}
</select>
3.2.6 dao接口参数是一个Map
  • map作为dao接口的参数,使用key获取参数值,在mapper文件中,语法格式#{key}
  • dao接口中的方法定义:
/**
   使用Map作为参数
*/
List<Student> selectStudentByMap(Map<String,Object> map);
  • mapper文件:
 <!--
     使用Map传递参数,
     在mapper文件中,获取map的值,是通过key获取的,语法,#{key}
	-->
<select id="selectStudentByMap" resultType="com.kgc.pojo.Student">
    select * from student where name=#{name} or age=#{age}
</select>
  • 测试调用方法的位置:
@Testpublic void testInsertByMap() throws IOException {    SqlSession session = MyBatisUtil.getSqlSession();    StudentDao dao = session.getMapper(StudentDao.class);    HashMap<String, Object> data = new HashMap<>();    data.put("name","李四");    data.put("age",14);    List<Student> students = dao.selectStudentByMap(data);    System.out.println(students);    MyBatisUtil.close(session);}

3.3 #和$的区别

3.3.1 #占位符
  • 语法:#{字符}
  • mybatis处理#{} 使用jdbc对象是PreparedStatement对象
<select id="getStudentById" parameterType="int"
        resultType="com.kgc.pojo.Student">
    select * from student where id = #{id}
</select>
mybatis创建出PreparedStatement对象,执行sql语句
String sql = "select * from student where id = ?"
PreparedStatement pst = com.PreparedStatement(sql);
pst.setInt(1,1001);//传递参数
ResultSet rs = pst.executeQuery();//执行sql语句
  • #{}特点:
    1. 使用的PreparedStatement对象,执行sql语句,效率高。
    2. 使用的PreparedStatement对象,能避免sql注入,sql语句执行更安全
    3. #{}常常作为列值使用的,位于等号的右侧,#{}位置的值和数据类型有关的
3.3.2 $占位符
  • 语法:${字符}

  • mybatis执行${}占位符的sql语句

<select id="getStudentById" parameterType="int"
        resultType="com.kgc.pojo.Student">
    select * from student where id = ${id}
</select>
${}表示字符串的连接,把sql语句的其他内容和${}内容使用字符串(+)连接的方式连在一起
String sql = "select * from student where id = "+"1001";
mybatis创建Statement对象,执行sql语句
Statement stmt = com.createStatement(sql);
ResultSet rs = stmt.executeQuery();
  • ${}的特点:

    1. 使用Statement对象,执行sql语句,效率低
    2. ${}占位符的值,使用的字符串连接的方式,有sql注入的风险。有代码安全的问题
    3. ${}数据是原样使用的,不会区分数据类型
    4. 常 用 作 为 表 名 或 者 列 名 , 在 能 保 证 数 据 安 全 的 情 况 下 使 用 {}常用作为表名或者列名,在能保证数据安全的情况下使用 使{}
  • dao接口中的方法定义:

/**
 * ${}占位符的使用,使用@Param命名
 */
List<Student> selectStudentOrderByName(@Param("colName")String name);
  • mapper文件:
<!--${}-->
<select id="selectStudentOrderByName" resultType="com.kgc.pojo.Student">
    select * from student order by #{colName} desc
</select>
  • 测试调用方法的位置:
@Test
public void testInsertByMap() throws IOException {
    SqlSession session = MyBatisUtil.getSqlSession();
    List<Student> students = dao.selectStudentOrderByName("id");
    System.out.println(students);
    MyBatisUtil.close(session);
}

3.4 封装Mybatis输出结果

  • 封装输出结果:MyBatis执行sql语句,得到ResultSet,转为java对象
  • 主要使用:resultType和resultMap
3.4.1 resultType
  • resultType属性:在执行select时使用,作为标签的属性出现的
  • reslutType表示结果类型,mybatis执行sql语句,得到java对象的类型,它的值有两种
    1. java类型的全限定名称
    2. 使用别名
  1. resultType表示java自定义对象
Student getStudentById(Integer id);
<select id="getStudentById" parameterType="int"
        resultType="com.kgc.pojo.Student">
    select * from student where id = ${id}
</select>

resultType:现在使用java类型的全限定名称,表示的意思是mybatis执行sql语句,把ResultSet中的数据转为Student类型的对象。mybatis会做以下操作:
1.调用com.kgc.pojo.Student的无参构造方法,创建对象
Student student = new Student();//使用反射创建对象
2.同名的列赋值给同名的属性
student.setId(rs.getInt("id"));
studnet.setName(rs.getString("name"));
3.得到java对象,如果dao接口返回值是List类型,mybatis把student对象放入到List集合

所以执行Student student = dao.getStudentById(1001);得到数据库中id=1001这行数据
这行数据的列值,赋给了student对象的属性,你能得到student对象。就相当于id=1001这行数据
  1. resultType表示简单类型
  • dao方法:
long countStudent();
  • mapper文件:
<!--执行sql语句,得到的是一个值(一行一列)-->
<select id="countStudent" resultType="java.lang.Long">
    select count(*) from student
</select>
  1. resultType表示一个Map结构
  • dao方法:
//查询结果返回的是一个Map
Map<Object,Object> selectMap(@Param("id") Integer id);
  • mapper文件:
<!--
    执行sql语句得到一个Map结构数据,mybatis执行sql,把resultType转为map
    sql执行结果,列名作map的key,列值作为value
    sql执行得到是一个记录,,转为map结构是正确的
    dao接口返回的是员工map,sql语句最多能获取一行记录,多余一行是错误的
 -->
<select id="selectMap" resultType="map">
    select * from student where id = #{id}
</select>
3.4.2 resultMap
  • resultMap:结果映射。自定义列名和java对象属性的对应关系,常用在列名和属性名不同的情况
  • 用法:
    1. 先定义resultMap标签,指定列名和属性名称对应关系
    2. 在select标签使用resultMap属性,指定上面定义的resultMap的id值
<!--使用resultMap定义列和属性的关系-->
<!--
        定义resultMap
        id:给resultMap的映射关系起个名称,唯一值
        type:java类型的全限定名称
    -->
<resultMap id="StudentMap" type="com.kgc.pojo.Student">
    <!--定义列名和属性名的对应-->
    <!--主键类型使用id标签-->
    <id column="id" property="cid"/>
    <!--非主键类型使用result标签-->
    <result column="name" property="cname"/>
    <!--列名和属性名相同可以不用定义-->
    <result column="email" property="email"/>
    <result column="age" property="age"/>
</resultMap>
<!--使用resultMap属性,指定映射关系 的id
        resultMap和resultType不能同时使用,二选一
    -->
<select id="getStudentById" resultMap="StudentMap">
    select * from student where id = #{id}
</select>
  • 复杂的属性:我们需要单独处理的对象或者集合
    • association:是resultMap的子元素,用于处理对象
      • 属性:javaType:指定属性的类型
    • collection:是resultMap的子元素,用于处理集合
      • 属性:ofType:集合中的泛型信息

3.5 自定义别名

  • mybatis提供的对java类型定义简短、好记的名称
  • 自定义别名的步骤:
    1. 在mybatis主配置文件,使用typeAliase标签声明别名
    2. 在mapper文件中,resultType=“别名”
  • 第一种方式:
  • 声明别名(mybatis主配置文件):
<!--定义别名-->
<typeAliases>
    <!--
        第一种语法格式
        type:java类型的全限定名称(自定义类型)
        alias:自定义别名
		优点:别名可以自定义
		缺点:每个类型必须单独定义
    -->
    <typeAlias type="com.kgc.pojo.Student" alias="stu"/>
</typeAliases>
  • mapper文件:
<!--resultType='别名'--><select id="getStudentById" parameterType="int"resultType="stu">    select * from student where id = ${id}</select>
  • 第二种方式:
  • 声明别名(mybatis主配置文件):
<!--定义别名-->
<typeAliases>
    <!--
        第二种语法格式
        name:包名,mybatis会把这个包中所有类名作为别名(不用区分大小写)
		优点:使用方便,一次给多个类定义别名
		缺点:别名不能自定义,必须是类名
     -->
    <package name="com.kgc.pojo"/>
</typeAliases>
  • mapper文件:
<!--resultType='类名'-->
<select id="getStudentById" parameterType="int"resultType="student">
    select * from student where id = ${id}
</select>

3.6 列名和java对象属性名称不一样解决方式

  1. 使用resultMap:自定义列名和属性名称对应关系
  2. 使用resultType:使用列的别名,让别名和java属性名称一样
<!--使用列别名,解决列名和属性名不同的问题-->
<select id="getStudentById" resultType="com.kgc.pojo.Student">
    select id as cid,name cname,email,age from student where id = #{id}
</select>

3.7 like

  • 第一种方式:在java程序中,把like的内容组装好,把这个内容传入到sql语句

  • dao方法:

//like第一种方式
List<Student> selectLikeOne(@Param("name") String name);
  • mapper文件:
<!--like第一种方式--><select id="selectLikeOne" resultType="com.kgc.pojo.Student">    select * from student where name like #{name}</select>
  • 测试调用方法:
@Testpublic void testInsertById() throws IOException {    SqlSession session = MyBatisUtil.getSqlSession();    StudentDao dao = session.getMapper(StudentDao.class);    String name = "%李%";    List<Student> students = dao.selectLikeOne(name);    MyBatisUtil.close(session);}
  • 第二种方式:在sql语句中,组织like的内容

  • sql语句中like的格式:select * from student where name like concat(’%’,#{name},’%’)

  • dao方法:

//like第二种方式List<Student> selectLikeOne(@Param("name") String name);
  • mapper文件:
<!--like第二种方式--><select id="selectLikeOne" resultType="com.kgc.pojo.Student">    select * from student where name like concat('%',#{name},'%')</select>
  • 测试调用方法:
@Test
public void testInsertById() throws IOException {
    SqlSession session = MyBatisUtil.getSqlSession();
    StudentDao dao = session.getMapper(StudentDao.class);
    String name = "李";
    List<Student> students = dao.selectLikeOne(name);
    MyBatisUtil.close(session);
}

第四章 动态sql

  • 说明是动态sql:同一个dao方法,根据不同的条件可以表示不同的sql语句,主要是where、set部分有变化
  • 使用mybatis提供的标签,实现动态sql的能力,主要是if、where、set、foreach,sql。
  • 使用动态sql的时候,dao方法的形参使用java对象
  • 一般在多条件查询时使用动态sql

4.1 if标签

  • 语法格式:
<if test="boolean判断结果">
    sql代码
</if>
  • 例如:
  • dao接口:
//if
List<Student> selectIf(Student student);
  • mapper文件:
<!--if
    test:使用对象的属性值作为条件
 -->
<select id="selectIf" resultType="com.kgc.pojo.Student">
    select * from student
    where id =-1
    <if test="name!=null and name!=''">
        or name = #{name}
    </if>
    <if test="age>0">
        or age = #{age}
    </if>
</select>

4.2 where标签

  • 使用if标签时,容易引起sql语句语法错误,使用where标签解决if产生的语法问题

  • 使用时where里面是一个或多个if标签,当有一个if标签判断条件为true,where标签会转为WHERE关键字附加到sql语句的后面,如果if没有一个条件为true,就会忽略where和里面的if

  • if条件满足的话where标签会自动删除和最近的or或者and

  • 语法:

<where>
    <if test="条件1">sql语句1</if>
    <if test="条件2">sql语句2</if>
</where>
  • 例如:
  • dao接口:
//where
List<Student> selectWhere(Student student);
  • mapper文件:
<!--where-->
<select id="selectWhere" resultType="com.kgc.pojo.Student">
    select * from student
    <where>
        <if test="name!=null and name!=''">
            or name = #{name}
        </if>
        <if test="age>0">
            or age = #{age}
        </if>
    </where>
</select>

4.3 set标签

  • 用于在update语句,一般配合if标签使用

  • 使用时set里面是一个或多个if标签,当有一个if标签判断条件为true,set标签会转为SET关键字附加到sql语句的后面,如果if没有一个条件为true,就会忽略set和里面的if

  • if条件满足的话where标签会自动删除和最近的 ‘,

  • 语法:

<set>
    <if test="条件1">sql语句1</if>
    <if test="条件2">sql语句2</if>
    where sql语句
</set>
  • 例如:
  • dao接口:
//set
int updateSet(Student student);
  • mapper文件:
<!--set-->
<select id="updateSet" >
    select * from student
    <set>
        <if test="name!=null and name!=''">
             name = #{name},
        </if>
        <if test="age>0">
            or age = #{age},
        </if>
        where id =#{id}
    </set>
</select>

4.4 foreach标签

  • 使用foreach可以循环数组,list集合,一般使用在in语句中
  • 语法:
<foreach collection= "集合类型" open="开始的字符" close="结束的字符"
         item="集合中的成员" separator="集合成员之间的分隔符">
    #{item的值}
</foreach>
标签属性:
collection:表示,循环的对象是数组,还是list集合。如果dao接口方法的形参是数组,				    collection="array",如果dao接口的形参是List,collection="list"
open:循环开始时的字符。 sql.append("(");
close:循环结束时字符。  sql.append(")");
item:集合成员,自定义的变量。Integer item = idList.get(i);//item是集合成员
separator:集合成员之间的分隔符。 sql.append(",");//集合成员之间的分隔符
#{item的值}:获取集合成员的值。

  • 第一种方式:简单类型List
  • dao接口:
//foreach简单类型
List<Student> selectForeach(List<Integer> id);
  • mapper文件:
<!--foreach第一种方式,循环简单类型的List-->
<select id="selectForeach" resultType="com.kgc.pojo.Student">
    select * from student
    <if test="id!=null and id.size>0">
        where id in
        <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </if>
</select>
  • 第二种方式:对象类型List
  • dao接口:
//foreach简单类型
List<Student> selectForeach(List<Student> students);
  • mapper文件:
<!--foreach第二种方式,循环对象类型的List-->
<select id="selectForeach" resultType="com.kgc.pojo.Student">
    select * from student
    <if test="id!=null and id.size>0">
        where id in
        <foreach collection="list" open="(" close=")" separator="," item="stu">
            #{stu.id}
        </foreach>
    </if>
</select>

4.5 choose标签

  • 有时我们不想应用到所有的条件语句,而只想从中选择其一项,就要用到choose标签,像是java中的switch语句

  • 要使用when标签和otherwise标签配合使用

    • when:判断该条件是否为true,满足则执行sql语句,不满足执行下一个
    • otherwise:表示when条件都不满足执行sql语句
  • 语法:

<choose>
    <when test="条件1">
        sql语句
    </when>
    <when test="条件2">
        sql语句
    </when>
    <otherwise>
       sql语句
    </otherwise>
</choose>

  • 例如:
  • dao接口:
//choose    
List<Student> getStudentChoose(Map<String,String> map);
  • mapper文件:
<!--choose-->
<select id="getStudentChoose" resultType="com.kgc.pojo.Student">
    select * from Student
    <where>
        <choose>
            <when test="name!=null and name!=''">
                name like concat('%',#{name},'%')
            </when>
            <when test="email!=null and email!=''">
                email like concat('%',#{email},'%')
            </when>
            <otherwise>
                age like concat('%',#{age},'%')
            </otherwise>
        </choose>
    </where>
</select>

4.6 trim标签

  • trim标签可以替代我们的set或者where标签,也是配合if标签使用
  • 属性:
    • prefix:给sql语句拼接的前缀
    • suffix:给sql语句拼接的后缀
    • prefixOverrides:前缀拼接字符或者关键字
    • suffixOverrides:后缀拼接字符或者关键字
  • where语法:
<select id="getUserList" resultType="User">
    SELECT * FROM smbms_user
    <trim prefix="where" prefixOverrides="and|or">
        <if test="name != null and name != ''">
            AND userName LIKE CONCAT('%',#{name},'%')
        </if>
        <if test="rid != null">
            AND userRole = #{rid}
        </if>
    </trim>
</select>
  • set语法:
<update id="updatePerson" parameterType="com.kgc.pojo.Person">
    update person
    <trim prefix="set" prefixOverrides="," suffix="where id=#{id}" >
        <if test="name!=null and name!=''">,name=#{name}</if>
        <if test="age!=null and age!=''">,age=#{age}</if>
        <if test="address!=null and address!=''">,address=#{address}</if>
        <if test="dept_id!=null and dept_id!=''">,dept_id=#{dept_id}</if>
    </trim>
</update>

4.7 sql标签

  • sql标签表示一段sql代码,可以是表名,几个字段,where条件都可以,可以在其他地方复用sql标签的内容
  • 使用方式:
1. 在mapper文件中定义,sql代码片段,<sql id="唯一字符串">部分sql语句</sql>
2. 在其他的位置,使用include标签引用某个代码片段
  • 例如:
<!--定义代码片段-->
<sql id="student">
    select * from student
</sql>
<select id="getStudentById" resultMap="StudentMap">
    <include refid="student"/>
    where id = #{id}
</select>

第五章 MyBatis配置文件

  • mybatis配置文件两大类:1.mybatis主配置文件;2.mybatis的mapper文件
    1. mybatis主配置文件,提供mybatis全局配置的。包括的内容有日志、数据源、mapper文件位置
    2. mapper文件:写sql语句的。一个表一个mapper文件

5.1 settings部分

  • settings是mybatis的全局设置,影响整个mybatis的运行。这个设置一般使用默认值就可以了。
<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

5.2 typeAliase 别名

  • 设置别名
<!--定义别名-->
<typeAliases>
    <!--
        第一种语法格式
        type:java类型的全限定名称(自定义类型)
        alias:自定义别名
		优点:别名可以自定义
		缺点:每个类型必须单独定义
    -->
    <typeAlias type="com.kgc.pojo.Student" alias="stu"/>
    <!--
        第二种语法格式
        name:包名,mybatis会把这个包中所有类名作为别名(不用区分大小写)
		优点:使用方便,一次给多个类定义别名
		缺点:别名不能自定义,必须是类名
     -->
    <package name="com.kgc.pojo"/>
</typeAliases>

5.3 配置环境

  • environments:环境标签,在它里面可以设置多个environment
    • 属性:default:必须是某个environment的id属性值,表示mybatis默认连接的数据库
  • environment:表示一个数据库的连接信息
    • 属性:id自定义环境的标识,唯一值
  • transactionManager:事务管理器
    • 属性:type表示事务管理器的类型
      1. JDBC:使用Connection对象,由mybatis自己完成事务的处理
      2. MANAGED:管理,表示把事务的处理交给容器实现(由其他软件完成事务的提交,回滚)
  • dataSource:数据源,创建的Connection对象,连接数据库
    • 属性:type表示数据源的类型
      1. POOLED:mybatis会在内存中创建PooledDataSource类,管理多个Connection连接对象,使用的连接池
      2. UNPOOLED:不使用连接池,mybatis创建一个UnPooledDataSource这个类,每次执行sql语句先创建Connection对象,再执行sql语句,最后关闭Connection
      3. JHDI:java的命名和目录服务
<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <!--配置数据源:创建Connection对象-->
        <dataSource type="POOLED">
            <!--driver:驱动的内容-->
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <!--连接数据库的url-->
            <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
            <!--用户名-->
            <property name="username" value="root"/>
            <!--密码-->
            <property name="password" value="ok"/>
        </dataSource>
    </environment>
</environments>

5.4 使用数据库属性配置文件(*)

  • 需要把数据库的配置信息放到一个单独文件中,独立管理。这个文件扩展名是properties,在这个文件中,使用自定义的key=value的格式表示数据
  • 使用步骤:
    1. 在resources目录中,创建XXX.properties
    2. 在文件中,使用key=value的格式定义数据
      • 例如:jdbc.url=jdbc:mysql://localhost:3306/springdb
    3. 在mybatis主配置文件,使用properties标签引用外部的属性配置文件
    4. 在使用值的位置,使用${key}获取key对应的value(等号右侧的值)
  • 例子:
  • db.properties:
driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/dbuseUnicode=true&amp;characterEncoding=utf-8username=rootpassword=ok
  • mybatis主配置文件:
<!--使用外部属性配置文件    resource:指定类路径下的某个属性配置文件 --><properties resource="db.properties"/><environments default="development">    <environment id="development">        <transactionManager type="JDBC"/>        <!--配置数据源:创建Connection对象-->        <dataSource type="POOLED">            <!--driver:驱动的内容-->            <property name="driver" value="${driver}"/>            <!--连接数据库的url-->            <property name="url" value="${url}"/>            <!--用户名-->            <property name="username" value="${username}"/>            <!--密码-->            <property name="password" value="${password}"/>        </dataSource>    </environment></environments>

5.5 mapper 标签(*)

  • 使用mapper指定其他mapper文件的位置
  • mapper标签使用的格式有两个常用的方式:
<mappers>    <!--第一种方式:resources="mapper文件的路径"        优点:文件清晰。加载的文件是明确的             文件的位置比较灵活        缺点:文件比较多,代码量会比较大,管理难度大-->    <mapper resource="com/kgc/dao/StudentDao.xml"/>    <!--        第二种方式:使用package        name:包名,mapper文件所在的包名        特点:把这个包中的所有mapper文件,一次加载        使用要求:        1. mapper文件和dao接口在同一目录        2. mapper文件大dao接口名称完全一样     -->    <package name="com.kgc.dao"/></mappers>

第六章 pageHelper(分页)

  • pageHelper做数据分页的,在你的select语句后面加入分页的sql内容,如果你使用的mysql数据库,他就会在select * from student后面加入 limit 语句。

  • 使用步骤:

    1. 加入依赖pageHelper依赖
    <dependency>    <groupId>com.github.pagehelper</groupId>    <artifactId>pagehelper</artifactId>    <version>5.1.10</version></dependency>
    
    1. 在mapper主配置文件,加入plugin声明
    <environments>之前加入<plugins>	<plugin interceptor="com.github.pagehelper.PageInterceptor"/></plugins>
    
    1. 在select语句之前,调用PageHelper.startPage(页码,每页条数)
  • 对比:

    • 没有使用PageHelper输出:select * from student order by id
    • 使用PageHelper输出:select * from student order by id limit ?
  • 例子:

  • dao接口:

//使用PageHelper分页List<Student> getStudent();
  • mapper文件:
<!--使用PageHelper分页--><select id="getStudent" resultType="com.kgc.pojo.Student">    select * from student order by id</select>
  • 测试方法:
@Testpublic void textPageHelper() throws IOException {    SqlSession session = MyBatisUtil.getSqlSession();    StudentDao dao = session.getMapper(StudentDao.class);    //调用PageHelper的方法    PageHelper.startPage(2,3);    List<Student> student = dao.getStudent();    for (Student student1 : student) {        System.out.println(student1);    }    session.close();}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我走后的夜与昼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值