Mybatis

Java框架-Mybatis

框架概述

框架简介

  • 框架指定是一系列工具类,它是个半成品,基于框架开发,可以提高效率
  • 框架是我们软件开发中的一套解决方案,不同的框架解决的是不同的问题
  • 使用框架的好处:
    • 框架封装了很多的细节,使开发者可以使用极简的方式实现功能,大大提高开发效率

三层架构

架构类名作用
表现层controller用于展示数据
业务层service处理业务逻辑
持久层dao和数据库交互

回顾JDBC操作数据库

  • 步骤
    1. 加载驱动
    2. 获取连接
    3. 定义要执行的语句
    4. 创建要执行sql语句的预编译处理对象并设置参数
    5. 执行sql语句
    6. 处理结果集
    7. 关闭连接,释放资源
  • 问题
    1. 频繁的创建连接关闭连接,耗费资源
      • 连接池可以解决这个问题
    2. 将sql语句硬编码到项目中,每次修改sql语句都会导致重新编译
      • 将sql语句配置到xml文件中
    3. 传递sql语句的参数,也会出现硬编码
      • 将参数传递到xml文件中

持久层技术解决方案

  • JDBC技术
    • Connection
    • PreparedStatement
    • ResultSet
  • Spring的JdbcTemplate
    • Spring中对Jdbc的简单封装
  • Apache的DBUtils
    • 它和Spring的JdbcTemp很像,也是对Jdbc的简单封装
  • 以上这些都不是框架
    • JDBC是规范
    • Spring的JdbcTemplate和Apache的DbUtils都只是工具类

Mybatis上

Mybatis概述

  • mybatis是一个持久层的框架,用java编写的
  • 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接等繁杂过程
  • mybatis是一个支持自定义sql语句的半自动框架
  • 它使用了ORM思想实现了结果集的封装
  • ORM
    • Object Relational Mapping 对象关系映射
    • 简单的说
      • 就是把关系型数据库表和实体类及实体类的属性一一对应起来
      • 让我们可以操作实体类就行实现操作数据库表
      • 实体类中的属性和数据库表的字段名称保持一致
  • 官方文档定义
    • MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
    • 官方文档: https://mybatis.org/mybatis-3/zh/index.html

Mybatis入门

  • Mybatis的环境搭建

    1. 创建maven工程并导入坐标

      • <?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.danny</groupId>
            <artifactId>mybatisDemo1_annotation</artifactId>
            <version>1.0-SNAPSHOT</version>
            <dependencies>
                <dependency>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis</artifactId>
                    <version>3.5.2</version>
                </dependency>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.47</version>
                </dependency>
                <dependency>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                    <version>1.2.17</version>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.13</version>
                    <scope>test</scope>
                </dependency>
            </dependencies>
        </project>
        
    2. 创建实体类和dao的接口

    3. 创建Mybatis的主配置文件 SqlMapConfig.xml

      • <?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="mysql">
                <!-- 配置mysql的环境 -->
                <environment id="mysql">
                <!-- 配置事务类型 -->
                    <transactionManager type="JDBC"></transactionManager>
                    <!-- 配置数据源(连接池) -->
                    <dataSource type="POOLED">
                        <!-- 配置连接数据库的4个基本信息 -->
                        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                        <property name="url" value="jdbc:mysql://localhost:3306/db_mybatis?serverTimezone=GMT%2B8&amp;characterEncoding=UTF-8"/>
                        <property name="username" value="root"/>
                        <property name="password" value="root"/>
                    </dataSource>
                </environment>
            </environments>
            <!-- 指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
             如果是用注解来配置的话,此处一个使用class属性指定被注解的dao全限定类名
             -->
            <mappers>
                <mapper class="com.danny.dao.IUserDao"/>
            </mappers>
        </configuration>
        
    4. 创建映射配置文件 IUserdao.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.danny.dao.IUserDao">
            <!--配置查询所有-->
            <select id="findAll" resultType="user">
                select * from user
            </select>
        </mapper>
        
  • 环境搭建的注意事项

    1. 创建IUserDao.xmlIUserDao.java时名称是为了我们之前的知识保持一致
      • 在Mybatis中它把持久层的操作接口名称和映射文件也叫做: Mapper
      • 所以: IUserdaoIUserMapper是一样的
    2. 在idea创建目录的时候,它和包是不一样的
      • 包在创建是: com.danny.dao它是三级结构
      • 目录创建时: com.danny.dao是一级目录
    3. 根据数据库列名创建实体类可以实现序列化接口用来提高传输速度
    4. Mybatis的映射配置文件位置必须和dao接口包结构相同
    5. 映射配置文件的mapper标签,namespace属性的取值必须是dao接口的全限定类名
    6. 映射配置文件的操作配置(select), id属性的取值必须是dao接口的方法名
    • 当我们遵从了第4,5,6点后,我们在开发中就无需再写dao的实现类
  • Mybatis入门案例

    • //1.读取配置文件
      InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
      //2.创建SqlSessionFactory工厂
      SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
      //3.使用工厂生产SqlSession对象
      SqlSession session = factory.openSession();
      //4.使用SqlSession创建Dao接口的代理对象
      IUserDao userDao = session.getMapper(IUserDao.class);
      //5.使用代理对象执行方法
      List<User> users = userDao.findAll();
      for (User user : users){
      	System.out.println(user);
      }
      //6.释放资源
      session.close();
      in.close();
      
      • 注意事项
        • 不要忘记在映射配置中告知mybatis要封装到哪个实体类中
        • 配置方式: 指定实体类的全限定类名
      • mybatis基于注解的入门案例:
        • IUserDao.xml移除,在dao接口的方法上使用@Select注解,并指定SQL语句
        • 同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名
      • 明确:
        • 我们在实际开发中,越简便越好,所以都是采用不写dao实现类的方式
        • 不管使用xml还是注解配置
        • 但是Mybatis是支持写dao实现类的
      • 自定义Mybatis的分析:
        • mybatis在使用代理dao的方式实现增删改查时只做两件事
          1. 创建代理对象
          2. 在代理对象中调用selectList

Mybatis框架主配置文件

  • <properties>属性标签

    1. 首先读取在 properties 元素体内指定的属性。
    2. 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
    3. 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
    • 优先级3>2>1

    • <!--定义属性变量,通过${变量名}来获取变量-->
      <properties>
          <property name="driver" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8"/>
          <property name="username" value="root"/>
          <property name="password" value="123456"/>
      </properties>
      <!--引入外部属性文件,通过${变量名}来获取变量值-->
      <properties resource="db.properties"></properties>
      
  • <settings>设置标签

    • 表示mybatis框架的配置特性标签,可以做各种特殊配置

    • <settings>
        <setting name="cacheEnabled" value="true"/>
      </settings>
      
    • 更多配置查看 https://mybatis.org/mybatis-3/zh/configuration.html#settings

  • <typeAliases>类别名标签

    • 该标签用于为数据类型取别名的标签

    • <!-- 单个与批量取别名只能二选一 -->
      <typeAliases>
          <!-- 单个取别名 -->
          <typeAlias type="com.danny.dao.IUserDao" alias="dao"/>
          <!-- 批量取别名 -->
          <package name="com.danny.dao"/>
      </typeAliases>
      
  • <typeHandlers>类型处理器标签(了解)

    • 作用将数据库字段数据类型转换java对象中的属性的数据类型, 或者反之
    • 用于注册自定义类型处理器,而mybatis已经提供了大量的类型处理器供我们使用,无需自定义
  • <objectFactory>对象工厂标签(了解)

    • 该标签用于注册自定义的工厂对象,而mybatis已经提供了工厂对象,不需要自己创建工厂对象
    • 创建数据库记录封装的对象实例
  • <plugins>插件标签

    • 该标签叫做插件标签,用于扩展其他功能,如扩展分页插件

    • 步骤

      1. 引入分页插件的jar包pom.xml

        • <dependency>
              <groupId>com.github.pagehelper</groupId>
              <artifactId>pagehelper</artifactId>
              <version>5.1.3</version>
          </dependency>
          
      2. 注册分页插件

        • <plugins>
              <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
          </plugins>
          
      3. 实现分页查询

        • @Test
          public void myTest2() throws IOException {
              String resource = "SqlMapConfig.xml";
              InputStream inputStream = Resources.getResourceAsStream(resource);
              SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              SqlSession session = sqlSessionFactory.openSession();
              PageHelper.startPage(2,3);
              List<User> users = session.selectList("org.mybatis.example.BlogMapper.selectBlog");
              for (User user : users){
                  System.out.println(user);
              }
              session.close();
              inputStream.close();
          }
          
  • <environments>环境标签

    • 该标签用于配置数据源

    • <!-- 配置环境 -->
          <!-- 指定数据源配置, 通过default属性指定要使用的具体的数据源 -->
          <environments default="mysql">
              <!-- 配置mysql的环境 -->
              <!-- 每一个environment就是一个数据源的配置, 属性id表示当前数据源的唯一标识 -->
              <environment id="mysql">
                  <!-- 配置事务类型 -->
                  <!-- transactionManager标签用于指定事务类型, 属性type取值有两个:
                   JDBC: 通过连接connection来实现事务管理;
                   MANAGED: 指定是容器类型的事务, 比如spring提供的事务;
                   -->
                  <transactionManager type="JDBC"/>
                  <!-- 配置数据源(连接池) -->
                  <!-- dataSource用于配置数据源的具体标签, 属性type表示获取连接的方式,取值有三个:
                   POOLED: 指的mybatis操作数据库时通过连接池的方式获取连接;
                   UNPOOLED: 指的是每次操作数据库都通过新建连接的方式获取链接;
                   JNDI: java命名注册接口, 指的是将数据源配置从项目中提取出来配置到TomCat服务器上通过远程固定api获取数据
                   作用将数据源和项目实现彻底解耦合
                   -->
                  <dataSource type="POOLED">
                      <!-- 配置连接数据库的4个基本信息 -->
                      <property name="driver" value="${db.driver}"/>
                      <property name="url" value="${db.url}"/>
                      <property name="username" value="${db.username}"/>
                      <property name="password" value="${db.password}"/>
                  </dataSource>
              </environment>
          </environments>
      
  • <databaseldProvider>数据库厂商标识标签(了解)

    • MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。

    • MyBatis 会加载带有匹配当前数据库 databaseId 属性和所有不带 databaseId 属性的语句

    • <databaseIdProvider type="DB_VENDOR">
        <property name="SQL Server" value="sqlserver"/>
        <property name="DB2" value="db2"/>
        <property name="Oracle" value="oracle" />
      </databaseIdProvider>
      
  • <mappers>映射器标签

    • 该标签用于引入配置映射文件,从而引入配置映射文件中的sql语句

      1. 使用相对于类路径的资源引用

        • <mappers>
            <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
            <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
            <mapper resource="org/mybatis/builder/PostMapper.xml"/>
          </mappers>
          
      2. 使用完全限定资源定位符(URL)

        • <mappers>
            <mapper url="file:///var/mappers/AuthorMapper.xml"/>
            <mapper url="file:///var/mappers/BlogMapper.xml"/>
            <mapper url="file:///var/mappers/PostMapper.xml"/>
          </mappers>
          
      3. 使用映射器接口实现类的完全限定类名

        • 必须保证接口和映射配置文件同名且同包

        • <mappers>
            <mapper class="org.mybatis.builder.AuthorMapper"/>
            <mapper class="org.mybatis.builder.BlogMapper"/>
            <mapper class="org.mybatis.builder.PostMapper"/>
          </mappers>
          
      4. 将包内的映射器接口实现全部注册为映射器

        • 必须保证接口和映射配置文件同名且同包

        • <mappers>
            <package name="org.mybatis.builder"/>
          </mappers>
          

Mybatis映射配置文件

  • <cache>标签

    • 该标签的作用是开启mybatis框架的二级缓存
  • <cache-ref>标签

    • 该标签的作用引入其他映射配置文件的缓存设置
  • <resultMap>标签

    • 该标签专门用于做高级映射,有两个使用场景:

      1. 当数据库表字段名称和javaBean对象属性名称不一致时,使用映射
      2. 当多表查询是,做高级映射使用
      <resultMap id="userMap" type="com.danny.entity.User">
          <id property="id" column="id" javaType="_int"/>
          <result column="username" property="username"/>
          <result column="birthday" property="birthday"/>
          <result column="sex" property="sex"/>
          <result column="address" property="address"/>
      </resultMap>
      
      • id:结果映射的唯一表示
        • type:指定查询结果返回的数据类型

        • <id>:映射主键字段

        • <result>:用于映射普通字段

          • 属性:
            • property指的是返回数据类型的属性名称; JavaType表示属性类型,可省略
            • column指定是查询数据库字段名称jdbcType表示字段标签,可以省略
  • <sql>标签

    • <!-- sql变量的定义 -->
      <sql id="selectUser">select id,username,birthday,sex,address from user</sql>
      <select id="selectAll" resultType="com.danny.entity.User">
          <!--include 表示sql语句变量的引用-->
          <include refid="selectUser"></include>
      </select>
      
    • 所有查询语句都必须指定返回类型: 指定方式有两种:

      • resultType属性指定:默认将数据库中的字段名称和java对象中属性名称相同的属性做映射
      • resultMap: 自定义结果映射, 一般用于查询字段名称和返回数据类型字段名称不一致时
  • <insert><update><delete><select>标签

    • 用于在映射配置文件中定义增删改查sql语句;
    • 属性:
      • id表示定义的sql语句的唯一标识;
      • <select>标签必须指定返回类型
        • resultType属性指定:默认将数据库中的字段名称和java对象中属性名称相同的属性做映射;
        • resultMap: 自定义结果映射, 一般用于查询字段名称和返回数据类型字段名称不一致时;

Mybatis执行原理

  • //定义mybatis主配置文件
    String resource = "SqlMapConfig.xml";
    //读取mybatis主配置文件,将其读取到输入流中
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //通过配置文件信息构建sqlSessionFactory对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //获取sqlSession对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //执行sql语句操作数据库
    User user = sqlSession.selectOne("org.mybatis.example.BlogMapper.selectOne");
    System.out.println(user);
    //持久化数据到数据库(提交事务,mybatis默认开启事务)
    sqlSession.commit();
    //关闭sqlSession释放资源
    sqlSession.close();
    inputStream.close();
    

基于接口代理的方式操作数据库

  • 步骤

    1. 引入mybatis的jar包

    2. 创建mybatis的两个配置文件,并配置好主配置文件

    3. 定义dao层接口

      • package com.danny.dao;
        import com.danny.entity.User;
        import org.apache.ibatis.annotations.Select;
        import java.util.List;
        /**
         * 用户的持久层接口
         */
        public interface IUserDao {
            /**
             * 查询所有操作
             * @return
             */
            @Select("Select * from user")
            List<User> findAll();
        
            /**
             * 新增
             * @param user
             */
            void insert(User user);
        
            /**
             * 修改
             * @param user
             */
            void update(User user);
        
            /**
             * 删除
             * @param id
             */
            void delete(int id);
        
            /**
             * 查询单个
             * @param id
             */
            User findUserById(int id);
        }
        
    4. 找到对应的映射配置文件,定义接口方法对应的接口语句

      • 要保证映射配置文件中namespace属性值和接口的全限定类名一致
    • 要保证sql语句的id值和接口方法名称一致

    •   <?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.danny.dao.IUserDao">
            <!-- 基于接口代理方式操作数据库,要保证映射配置文件中namespace属性值和接口的全限定类名一致;
             要保证sql语句的id值和接口方法名称一致-->
            <select id="findUserById" resultType="user">
                select id,username,birthday,sex,address from user where id = #{id}
          </select>
            <insert id="insert" parameterType="user">
                insert into user (id,username,birthday,sex,address) values(default,#{username},#{birthday},#{sex},#{address})
          </insert>
            <update id="update" parameterType="user">
                update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
          </update>
            <delete id="delete" parameterType="user">
                delete from user where id=#{id}
          </delete>
        </mapper>
      
    1. 使用接口代理对象操作数据库

    2. 将新增的接口

提取工具类操作数据库

  • 工具类

    • public class MySqlSessionFactory {
          private static SqlSessionFactory sqlSessionFactory;
          private static InputStream in;
          static {
              //1.读取配置文件
              try {
                  in = Resources.getResourceAsStream("SqlMapConfig.xml");
              } catch (IOException e) {
                  e.printStackTrace();
              }
              //2.创建SqlSessionFactory工厂
              sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
          }
          public static SqlSessionFactory getSqlSessionFactory(){
              return sqlSessionFactory;
          }
      }
      
  • 测试类

    • public class MybatisTest02 {
          private IUserDao userDao;
          private SqlSession session;
          private InputStream in;
          @Before
          public void before() throws IOException {
              //3.使用工厂生产SqlSession对象
              session = MySqlSessionFactory.getSqlSessionFactory().openSession();
              //4.使用SqlSession创建Dao接口的代理对象
              userDao = session.getMapper(IUserDao.class);
          }
          @After
          public void after() throws IOException {
              session.commit();
              //6.释放资源
              session.close();
          }
          @Test
          public void testFindUserById() throws Exception {
              //5.使用代理对象执行方法
              User user = userDao.findUserById(48);
              System.out.println(user);
          }
      }
      
  • 映射文件

    • <?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.danny.dao.IUserDao">
          <!-- 基于接口代理方式操作数据库,要保证映射配置文件中namespace属性值和接口的全限定类名一致;
           要保证sql语句的id值和接口方法名称一致-->
          <select id="findUserById" resultType="user">
              select id,username,birthday,sex,address from user where id = #{id}
        </select>
      </mapper>
      

Mybatis的参数传递

  • 单参数传递

    • mybatis在传递单个参数时, 映射配置文件中的sql语句占位符中参数名称可以随便写,因为它是根据类型来传递参数的
  • 多参数传递

    1. 最常用的: 多参数传递时, 将多个参数封装到对象中进行传递,mybatis会根据对象属性名来设置占位符中的参数

    2. 直接传递多个参数, mybatis通过索引来设置sql语句中占位符的参数

      • 接口中的方法使用多个参数代替javaBean实体对象

      • sql语句中使用索引#{arg0},#{arg1}

    3. 直接传递多个参数, 在每个参数前加上注解@param,mybatis可以通过注解名称获取参数名来设置sql语句中占位符的参数

    4. 将多个参数封装到map集合中进行传递,mybatis会根据map集合中的key值类设置占位符中的参数

  • mybatis传参中的#{}${}

    • #{}, 相当于占位符, 可以防止sql注入

    • ${}, 仅仅相当于字符串, 不能防止sql注入

    • 模糊搜索案例:

      List<Car> findCarsByCname(String cname);
      List<Car> findCarsByCname2(@Param("cname") String cname);
      
      <select id="findCarsByCname" resultType="car">
          select cid,car_name as carName,car_price as carPrice from car where car_name like concat('%',#{cname},'%')
      </select>
      <select id="findCarsByCname2" resultType="car">
          select cid,car_name as carName,car_price as carPrice from car where car_name like '%${cname}%'
      </select>
      

Mybatis中

一对一关系多表查询

  1. 嵌套结果集方式

    1. 定义dao层接口

      • public interface IUserOrderDao {
            /**
             *
             * @param uid
             * @return
             */
            User findUserOrderByUid(int uid);
        }
        
    2. 创建对应的映射文件,定义接口方法对应执行的sql语句

      • <?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.danny.dao.IUserOrderDao">
            <!-- 一对一关系多表查询 -->
            <resultMap id="userOrderResult" type="User">
                <id property="id" column="id" javaType="_int"/>
                <result column="username" property="username"/>
                <result column="birthday" property="birthday"/>
                <result column="sex" property="sex"/>
                <result column="address" property="address"/>
                <!-- 该标签表示一对一关系表映射 -->
                <association property="order" javaType="Order">
                    <id column="id" property="oid"/>
                    <result column="user_id" property="userId"/>
                    <result column="sum_price" property="sumPrice"/>
                    <result column="created_time" property="createdTime"/>
                    <result column="info" property="info"/>
                </association>
            </resultMap>
            <select id="findUserOrderByUid" resultMap="userOrderResult">
            SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id,o.user_id,o.sum_price,o.created_time,o.info FROM USER u
            LEFT JOIN `order` o ON u.id=o.user_id WHERE u.id=1
        </select>
        </mapper>
        
    3. 使用MybatisAPI操作数据库

      • public class myTest {
            private SqlSession session;
            private IUserOrderDao userOrderDao;
        
            @Before
            public void before() throws IOException {
                //3.使用工厂生产SqlSession对象
                session = MySqlSessionFactory.getSqlSessionFactory().openSession();
                //4.使用SqlSession创建Dao接口的代理对象
                userOrderDao = session.getMapper(IUserOrderDao.class);
            }
            @After
            public void after() throws IOException {
                //6.释放资源
                session.close();
            }
            /**
             * 一对一关系多表查询
             * 嵌套结果集方式
             */
            @Test
            public void test1(){
                User uu = userOrderDao.findUserOrderByUid(1);
                System.out.println(uu);
            }
        }
        
  2. 嵌套查询方式操作数据库

    1. 定义dao层接口

      • /**
         * 嵌套查询方式
         * @param uid
         * @return
         */
        User findUserOrderByUid(long uid);
        
    2. 找到对应的映射文件,定义接口方法对应执行的sql语句

      1. 第一步sql语句

        • <!-- 一对一嵌套查询 -->
              <resultMap id="userOrderResult2" type="user">
                  <id property="id" column="id" javaType="_int"/>
                  <result column="username" property="username"/>
                  <result column="birthday" property="birthday"/>
                  <result column="sex" property="sex"/>
                  <result column="address" property="address"/>
                  <!--association表示一对一映射表关系
                  column属性表示传入嵌套查询sql语句的入参;
                  select属性表示下一步嵌套查询的sql语句-->
                  <association property="order" column="id" select="com.danny.dao.OrderDao.findOrderByUid">
                  </association>
              </resultMap>
              <!-- 定义第一步sql语句 -->
              <select id="findUserOrderByUid2" resultMap="userOrderResult2">
                  select id,username,birthday,sex,address from user where id = #{id}
              </select>
          
      2. 第二步sql语句

        • <?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.danny.dao.OrderDao">
              <resultMap id="orderMap" type="order">
                              <id column="id" property="oid"/>
                              <result column="user_id" property="userId"/>
                              <result column="sum_price" property="sumPrice"/>
                              <result column="created_time" property="createdTime"/>
                              <result column="info" property="info"/>
              </resultMap>
              <select id="findOrderByUid" resultMap="orderMap">
              SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id};
            </select>
          </mapper>
          
    3. 使用MybatisAPI操作数据库

      • /**
             * 一对一关系多表查询
             * 嵌套查询方式
             */
            @Test
            public void test2(){
                User uu = userOrderDao.findUserOrderByUid2(1);
                System.out.println(uu);
            }
        

一对多关系多表操作

  1. 嵌套结果集方式

    1. 定义dao层接口

      • /**
         * 嵌套结果集
         * @param uid
         * @return
         */
        List<User> findUserOrdersByUid(int uid);
        
    2. 使用dao层接口代理处理数据库

      • <!-- 一对多关系多表查询 -->
        <resultMap id="userOrdersResult" type="User">
            <id property="id" column="id" javaType="_int"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            <!-- 该标签表示一对多关系表映射 -->
            <collection property="orderList" ofType="Order">
                <id column="oid" property="oid"/>
                <result column="user_id" property="userId"/>
                <result column="sum_price" property="sumPrice"/>
                <result column="created_time" property="createdTime"/>
                <result column="info" property="info"/>
            </collection>
        </resultMap>
        <select id="findUserOrdersByUid" resultMap="userOrdersResult">
        SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id as oid,o.user_id,o.sum_price,o.created_time,o.info FROM USER u
        LEFT JOIN `order` o ON u.id=o.user_id WHERE u.id=#{id}
        </select>
        
    3. 使用MybatisAPI操作数据库

      • /**
         * 一对多关系多表查询
         * 嵌套结果集方式
         */
        @Test
        public void test3(){
            List<User> uu = userOrderDao.findUserOrdersByUid(2);
            System.out.println(uu);
        }
        
  2. 嵌套查询方式操作数据库

    1. 定义dao层接口

      • /**
         * 嵌套查询方式
         * @param uid
         * @return
         */
        List<User> findUserOrdersByUid2(int uid);
        
    2. 使用dao层接口代理处理数据库

      1. 第一步sql语句

        • <!-- 一对多嵌套查询 -->
          <resultMap id="userOrdersResult2" type="user">
              <id property="id" column="id" javaType="_int"/>
              <result column="username" property="username"/>
              <result column="birthday" property="birthday"/>
              <result column="sex" property="sex"/>
              <result column="address" property="address"/>
          
              <collection property="orderList" column="id" select="com.danny.dao.OrderDao.findOrdersByUid">
              </collection>
          </resultMap>
          <!-- 定义第一步sql语句 -->
          <select id="findUserOrdersByUid2" resultMap="userOrdersResult2">
              select id,username,birthday,sex,address from user where id = #{id}
          </select>
          </mapper>
          
      2. 第二步sql语句

        • <select id="findOrdersByUid" resultMap="orderMap">
              SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id};
            </select>
          
    3. 使用MybatisAPI操作数据库

      • /**
         * 一对多关系多表查询
         * 嵌套查询方式
         */
        @Test
        public void test4(){
            List<User> uu = userOrderDao.findUserOrdersByUid2(2);
            System.out.println(uu);
        }
        

多对多关系多表操作

  1. 嵌套结果集方式

    1. 定义dao层接口

      • public interface IUserOrderItemDao {
            /**
             * 根据用户id获取用户订单商品信息(嵌套结果集方式)
             * @param uid
             * @return
             */
            List<User> findUserOrderItemByUid(int uid);
        }
        
    2. 使用dao层接口代理处理数据库

      • <!-- 多对多嵌套结果集方式 -->
        <resultMap id="userOrdersItemsResult" type="User">
            <id property="id" column="id" javaType="_int"/>
            <result column="username" property="username"/>
            <result column="birthday" property="birthday"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
            <collection property="orderList" ofType="Order">
                <id column="oid" property="oid"/>
                <result column="user_id" property="userId"/>
                <result column="sum_price" property="sumPrice"/>
                <result column="created_time" property="createdTime"/>
                <result column="info" property="info"/>
                <association property="item" javaType="item">
                    <result column="order_id" property="orderId"/>
                    <result column="product_id" property="productId"/>
                    <result column="purchase_num" property="purchaseNum"/>
                    <collection property="productList" ofType="product">
                        <id column="pid" property="id"/>
                        <result column="name" property="name"/>
                        <result column="price" property="price"/>
                        <result column="info" property="info"/>
                        <result column="created_time" property="createTime"/>
                    </collection>
                </association>
            </collection>
        </resultMap>
        <select id="findUserOrderItemByUid" resultMap="userOrdersItemsResult">
        SELECT u.id,u.username,u.birthday,u.sex,u.address,o.id as oid,o.user_id,o.sum_price,o.created_time,o.info,i.order_id,i.product_id,i.purchase_num,p.id as pid,p.name,p.price,p.info,p.created_time
        FROM USER u
        LEFT JOIN `order` o ON u.id=o.user_id
        LEFT JOIN `order_item` i ON o.id=i.order_id
        LEFT JOIN `product` p ON i.product_id=p.id
        WHERE u.id=#{id}
        </select>
        
    3. 使用MybatisAPI操作数据库

      • /**
         * 多对多关系多表查询
         * 嵌套结果集方式
         */
        @Test
        public void test5(){
            List<User> uu = userOrderItemDao.findUserOrderItemByUid(2);
            System.out.println(uu);
        }
        
  2. 嵌套查询方式操作数据库

    1. 定义dao层接口

      • /**
         * 根据用户id获取用户订单商品信息(嵌套查询)
         * @param uid
         * @return
         */
        List<User> findUserOrderItemByUid2(int uid);
        
    2. 使用dao层接口代理处理数据库

      1. 第一步sql语句

        • <!-- 多对多嵌套查询方式 -->
          <resultMap id="userOrdersItemsResult2" type="user">
              <id property="id" column="id" javaType="_int"/>
              <result column="username" property="username"/>
              <result column="birthday" property="birthday"/>
              <result column="sex" property="sex"/>
              <result column="address" property="address"/>
          
              <collection property="orderList" column="id" select="com.danny.dao.OrderDao.findOrdersByUid2">
              </collection>
          </resultMap>
          <!-- 定义第一步sql语句 -->
          <select id="findUserOrderItemByUid2" resultMap="userOrdersItemsResult2">
              select id,username,birthday,sex,address from user where id = #{id}
          </select>
          
      2. 第二步sql语句

        • <!--多对多嵌套方法2-->
          <resultMap id="orderMaps" type="order">
              <id column="id" property="oid"/>
              <result column="user_id" property="userId"/>
              <result column="sum_price" property="sumPrice"/>
              <result column="created_time" property="createdTime"/>
              <result column="info" property="info"/>
              <association property="item" column="id" select="com.danny.dao.ItemDao.findItemByOid"></association>
          </resultMap>
          <select id="findOrdersByUid2" resultMap="orderMaps">
          SELECT id,user_id,sum_price,created_time,info FROM `ORDER` WHERE user_id = #{id};
          </select>
          
      3. 第三步sql语句

        • <mapper namespace="com.danny.dao.ItemDao">
          <resultMap id="itemResult" type="item">
              <result column="order_id" property="orderId"/>
              <result column="product_id" property="productId"/>
              <result column="purchase_num" property="purchaseNum"/>
              <collection property="productList" column="product_id" select="com.danny.dao.ProductDao.findProductsByPid">
              </collection>
          </resultMap>
          <select id="findItemByOid" resultMap="itemResult">
          SELECT order_id,product_id,purchase_num FROM order_item WHERE order_id= #{id}
          </select>
          </mapper>
          
      4. 第四步sql语句

        • <mapper namespace="com.danny.dao.ProductDao">
          <resultMap id="productResult" type="product">
              <id column="id" property="id"/>
              <result column="name" property="name"/>
              <result column="price" property="price"/>
              <result column="info" property="info"/>
              <result column="created_time" property="createTime"/>
          </resultMap>
          <select id="findProductsByPid" resultMap="productResult">
          SELECT id,NAME,price,info,created_time FROM product WHERE id = #{id}
          </select>
          </mapper>
          
    3. 使用MybatisAPI操作数据库

      • /**
         * 多对多关系多表查询
         * 嵌套结果集方式
         */
        @Test
        public void test6(){
            List<User> uu = userOrderItemDao.findUserOrderItemByUid2(2);
            System.out.println(uu);
        }
        

新增返回主键值

  1. 通过设置属性useGeneratedKeys返回主键

    •  <!--新增返回主键值:
          useGeneratedKeys表示是否设置新增返回主键id;
          keyproperty属性表示新增返回的主键值的具体位置-->
          <insert id="insertOrders" useGeneratedKeys="true" keyProperty="oid">
              insert into orders (pid,order_name) values(#{pid},#{orderName})
          </insert>
      
  2. 通过selectKey标签返回主键

    •     <insert id="insertOrders" >
              <selectKey resultType="_long" keyProperty="oid">
                  SELECT LAST_INSERT_ID()
              </selectKey>
              insert into orders (pid,order_name) values(#{pid},#{orderName})
          </insert>
      

Mybatis下

Mybatis的动态sql

  • Mybatis中的动态sql语句用于在xml文件中动态的拼接sql语句,可以自动的删除多余的前缀或者后缀,如逗号后缀and符号等,作用降低拼接sql语句的复杂程度,提高开发效率
<if>动态sql标签
  • if动态标签就相当于java中的if关键字,作用用于在sql语句中做条件判断

  • 示例

    • <select id="findProductsByOrderConditionWithIf" resultMap="productResult">
          <include refid="selectProduct"></include>
          <if test="'price'.equals(orderCondition)">
              order by price
          </if>
          <if test="'id'.equals(orderCondition)">
              order by id
          </if>
          <if test="'name'.equals(orderCondition)">
              order by name
          </if>
      </select>
      
<where>动态sql标签
  • where动态标签相当于sql语句中的where关键字,除了可以添加限制条件以外,还可以自动删除多余的前缀and符号; 通常搭配if动态标签使用,当if条件不成立时,自动删除多余前缀and符号

  • 示例

    • <select id="findProductsByConditionWithWhere" resultMap="productResult">
          <include refid="selectProduct"></include>
          <where>
              <if test="name!=null">
                  name like concat('%',#{name},'%')
              </if>
              <if test="price>0">
                  and price <![CDATA[<]]>#{price}
              </if>
          </where>
      </select>
      
<choose> <when> <otherwise>动态标签
  • 该标签相当于java中的switch case default 用于条件判断,可以用该动态标签替换上面的if+where动态标签

  • 示例

    • <select id="findProductsByOrderCondition" resultMap="productResult">
          <include refid="selectProduct"></include>
          <choose>
              <when test="'price'.equals(orderCondition)">
                  order by price
              </when>
              <when test="'name'.equals(orderCondition)">
                  order by name
              </when>
              <otherwise>
                  order by id
              </otherwise>
          </choose>
      </select>
      
<set>动态标签
  • set动态标签相当于sql语句中的set关键字,用于修改sql语句,除了修改以外,还可以自己删除多余的逗号,通常搭配id动态标签使用,当if条件成立时,删除多余逗号

  • 示例

    • <update id="updateProduct">
          update product
          <set>
              <if test="name!=null">
                  name=#{name},
              </if>
              <if test="price>0">
                  price=#{price},
              </if>
          </set>
          where id=#{id}
      </update>
      
<trim>动态标签
  • trim动态标签可以替换where动态标签和set动态标签,作用可以自动的添加前缀或者后缀,可以自动删除前缀后缀后缀
  • trim动态标签提供了四个属性
    • prefix

      • 用于指定自动增加的前缀
    • prefixOverrides

      • 用于指定自动删除的前缀
    • suffix

      • 用于指定自动增加的后缀
    • suffixOverrides

      • 用于指定自动删除的前缀
    • 示例

      • <update id="updateProduct2">
            update product
            <trim prefix="set" suffixOverrides=",">
                <if test="name!=null">
                    name=#{name},
                </if>
                <if test="price>0">
                    price=#{price},
                </if>
            </trim>
            where id=#{id}
        </update>
        
<foreach>动态标签
  • 相当于java中的for循环,用于sql语句中的迭代集合或者数组

  • foreach标签迭代集合或者数组,拼接批量操作sql语句

    • collection:
      • 表示要迭代的集合或者数组
        • 如果传入参数是单个参数,那么根据类型来取参数
        • 如果传入多个参数,那么根据多个参数传递规则获取参数
    • open:
      • 表示要迭代sql语句的前面部分
    • close:
      • 表示要迭代sql语句的后面部分
    • item:
      • 表示要迭代的集合或者数组中每一个元素为其定义的变量名
    • separator:
      • 表示要迭代的元素之间的分隔符
  • 示例

    • <select id="findProductsByPid" resultMap="productResult">
          SELECT id,NAME,price,info,created_time FROM product
          where id in
          <foreach collection="array" open="(" close=")" item="pid" separator=",">
              #{pid}
          </foreach>
      </select>
      

具体案例

  • https://mybatis.org/mybatis-3/zh/dynamic-sql.html

Mybatis懒加载

  • mybatis的懒加载又叫做按需加载或者延迟加载,根据需要去加载,需要就加载,不需要就不加载

    • 需要: 指的是用户的需求
    • 加载: 指的是加载要执行的sql语句

    注意: mybatis懒加载使用的前提,必须要有嵌套查询sql语句

  • 好处:先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。

  • 坏处: 因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗 时间,所以可能造成用户等待时间变长,造成用户体验下降。

  • 懒加载的使用(主配置文件)

    • 全局懒加载设置

      • <properties>标签后面

      • <settings>
            <setting name="lazyLoadingEnabled" value="true"/>
        </settings>
        
    • 局部懒加载设置

      • mybatis提供了两个标签<association><collection>里面有个属性fetchType可以设置局部懒加载
        • fetchType=lazy 开启懒加载
        • fetchType=eager关闭懒加载
      • 注意局部懒加载优先级高于全局懒加载

Mybatis的缓存机制

  • 缓存:指的是一块内存空间用于存储大量频繁访问的数据,当用户第一次读取数据库中的数据库时,会将这些数据查询出来存放到该内存空间中(缓存中),当用户再次获取同样的数据时,可以直接从内存中返回,而不用再去数据库中读取,从而提高查询效率;
  • 注意:每一次的新增,修改,删除数据库数据后悔导致缓存清空,除此之外mybatis提供了手动清空缓存的方法clearCache()
  • mybatis提供了两种缓存机制一级缓存和二级缓存机制
一级缓存
  • mybatis默认支持一级缓存
    • 一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
    • 一级缓存的作用范围(生命周期)
      • 随着sqlSession的创建而创建
      • 随着sqlSession的销毁而销毁
二级缓存
  • mybatis二级缓存的使用需要自己设置
    • 二级缓存的作用范围在一个mapper映射配置文件中
    • 二级缓存的生命周期
      • 随着sqlSessionFactory的创建而创建
      • 随着sqlSessionFactory的销毁而销毁
    • 多个用户共享这个缓存(跨sqlSession的缓存)
  • 二级缓存设置
    • 开启缓存,默认就是开启的
    • 在要开启二级缓存的mapper文件中加二级缓存设置<cache>
    • 具体配置了解:详见官方文档

逆向工程

  • 步骤

    1. 引入mybatis逆向工程jar包

      • <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        
    2. 配置逆向工程的配置文件

      • <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE generatorConfiguration
                PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
                "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
        <generatorConfiguration>
            <!-- context 是逆向工程的主要配置信息 -->
            <!-- id:起个名字 -->
            <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 -->
            <context id="default" targetRuntime="MyBatis3">
                <!--optional,指在创建class时,对注释进行控制-->
                <commentGenerator>
                    <property name="suppressDate" value="true"/>
                    <!-- 是否去除自动生成的注释 true:是 : false:否 -->
                    <property name="suppressAllComments" value="true"/>
                </commentGenerator>
                <!--jdbc的数据库连接 wg_insert 为数据库名字-->
                <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                                connectionURL="jdbc:mysql://localhost:3306/db_mybatis_orders?useUnicode=true&amp;characeterEncoding=utf-8&amp;serverTimezone=UTC"
                                userId="root"
                                password="root"/>
                <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制-->
                <javaTypeResolver>
                    <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 -->
                    <!-- 不是 double 和 long 类型 -->
                    <!-- 使用常用的基本类型代替 sql 包下的引用类型 -->
                    <property name="forceBigDecimals" value="false"/>
                </javaTypeResolver>
                <!-- targetPackage:生成的实体类所在的包 -->
                <!-- targetProject:生成的实体类所在的硬盘位置 -->
                <javaModelGenerator targetPackage="com.danny.bean"
                                    targetProject="src/main/java">
                    <!-- 是否允许子包 -->
                    <property name="enableSubPackages" value="true"/>
                    <!-- 是否对modal添加构造函数 -->
                    <property name="constructorBased" value="true"/>
                    <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
                    <property name="trimStrings" value="true"/>
                    <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
                    <property name="immutable" value="false"/>
                </javaModelGenerator>
                <!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 -->
                <sqlMapGenerator targetPackage="mapper"
                                 targetProject="src/main/resources">
                    <!-- 针对数据库的一个配置,是否把 schema 作为字包名 -->
                    <property name="enableSubPackages" value="true"/>
                </sqlMapGenerator>
                <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 -->
                <javaClientGenerator type="XMLMAPPER"
                                     targetPackage="com.danny.dao" targetProject="src/main/java">
                    <!-- 针对 oracle 数据库的一个配置,是否把 schema 作为字包名 -->
                    <property name="enableSubPackages" value="true"/>
                </javaClientGenerator>
                <!-- tableName是数据库中的表名,domainObjectName是生成的JAVA模型名,后面的参数不用改,要生成更多的表就在下面继续加table标签 -->
        <!--        <table tableName="student" domainObjectName="Student"-->
        <!--               enableCountByExample="false" enableUpdateByExample="false"-->
        <!--               enableDeleteByExample="false" enableSelectByExample="false"-->
        <!--               selectByExampleQueryId="false"></table>-->
        
                <table tableName="user"/>
                <table tableName="order"/>
                <table tableName="order_item"/>
                <table tableName="item"/>
            </context>
        </generatorConfiguration>
        
    3. 使用逆向工程API运行

      • import org.junit.Test;
        import org.mybatis.generator.api.MyBatisGenerator;
        import org.mybatis.generator.config.Configuration;
        import org.mybatis.generator.config.xml.ConfigurationParser;
        import org.mybatis.generator.internal.DefaultShellCallback;
        
        import java.io.File;
        import java.util.ArrayList;
        import java.util.List;
        
        public class testGenerator {
            @Test
            public void testBuild() throws Exception {
                List<String> warnings = new ArrayList<String>();
                boolean overwrite = true;
                File configFile = new File("src/mybatisGenerator.xml");
                ConfigurationParser cp = new ConfigurationParser(warnings);
                Configuration config = cp.parseConfiguration(configFile);
                DefaultShellCallback callback = new DefaultShellCallback(overwrite);
                MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
                myBatisGenerator.generate(null);
            }
        }
        

逆向工程方法总结

  • mapper接口中的方法解析
    • mapper接口中的部分常用方法及功能如下:
方法功能说明
int countByExample(UserExample example) thorws SQLException按条件计数
int deleteByPrimaryKey(Integer id) thorws SQLException按主键删除
int deleteByExample(UserExample example) thorws SQLException按条件删除
String/Integer insert(User record) thorws SQLException插入数据(返回值为ID)
User selectByPrimaryKey(Integer id) thorws SQLException按主键查询
ListselectByExample(UserExample example) thorws SQLException按条件查询
ListselectByExampleWithBLOGs(UserExample example) thorws SQLException按条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生
int updateByPrimaryKey(User record) thorws SQLException按主键更新
int updateByPrimaryKeySelective(User record) thorws SQLException按主键更新值不为null的字段
int updateByExample(User record, UserExample example) thorws SQLException按条件更新
int updateByExampleSelective(User record, UserExample example) thorws SQLException按条件更新值不为null的字段
  • Example类解析
    • mybatis的逆向工程中会生成实体类及实体类对应的example类,example类用于添加条件,相当where后面的部分。
    • xxxExample example = new xxxExample();
    • Criteria criteria = new Example().createCriteria();
    • example类中的部分常用方法及功能如下:
方法功能说明
example.setOrderByClause(“字段名 ASC”);添加升序排列条件,DESC为降序
example.setDistinct(false)去除重复,boolean型,true为选择不重复的记录
criteria.andXxxIsNull添加字段xxx为null的条件
criteria.andXxxIsNotNull添加字段xxx不为null的条件
criteria.andXxxEqualTo(value)添加xxx字段等于value条件
criteria.andXxxNotEqualTo(value)添加xxx字段不等于value条件
criteria.andXxxGreaterThan(value)添加xxx字段大于value条件
criteria.andXxxGreaterThanOrEqualTo(value)添加xxx字段大于等于value条件
criteria.andXxxLessThan(value)添加xxx字段小于value条件
criteria.andXxxLessThanOrEqualTo(value)添加xxx字段小于等于value条件
criteria.andXxxIn(List<?>)添加xxx字段值在List<?>条件
criteria.andXxxNotIn(List<?>)添加xxx字段值不在List<?>条件
criteria.andXxxLike(“%”+value+”%”)添加xxx字段值为value的模糊查询条件
criteria.andXxxNotLike(“%”+value+”%”)添加xxx字段值不为value的模糊查询条件
criteria.andXxxBetween(value1,value2)添加xxx字段值在value1和value2之间条件
criteria.andXxxNotBetween(value1,value2)添加xxx字段值不在value1和value2之间条件
  • 注:在mybatis逆向工程生成的文件XxxExample.java中包含一个static的内部类Criteria,Criteria中的方法是定义SQL 语句where后的查询条件。
  • 总结
    • XxxExample.java只能实现简单条件增删改查,复杂的功能还需要自己编写sql代码来实现。

Mybatis注解配置

  • 以下注解都是在接口方法上配置

    • @Insert : 插入sql , 和xml insert sql语法完全一样
    • @Select : 查询sql, 和xml select sql语法完全一样
    • @Update : 更新sql, 和xml update sql语法完全一样
    • @Delete : 删除sql, 和xml delete sql语法完全一样
    • @Param : 入参
    • @Results:该注解相当于xml中的<resultMap>标签,用于自定义结果映射;
    • @Result:该注解相当于xml中的<result>标签,用于字段映射;
    • @One:该注解相当于xml中的<association>标签,用于一对一表映射;
    • @Many:该注解相当于xml中的<collection>标签,用于一对多表映射;
  • @SelectProvider: 实现动态 SQL 映射

    • @CacheNamespace:实现注解二级缓存的使用
  • 单表增删改查

    1. 定义dao层接口以及对应的sql语句

      • /**
         * 新增
         * @param user
         */
        @Insert("insert into user (id,username,birthday,sex,address) values(default,#{username},#{birthday},#{sex},#{address})")
        void insert2(User user);
        
        /**
         * 修改
         * @param user
         */
        @Update("update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}")
        void update2(User user);
        
        /**
         * 删除
         * @param id
         */
        @Delete("delete from user where id=#{id}")
        void delete2(int id);
        
        /**
         * 查询单个
         * @param id
         */
        @Select("select id,username,birthday,sex,address from user where id=#{id}")
        User findUserById2(int id);
        
        /**
         * 查询所有操作
         * @return
         */
        @Select("Select id,username,birthday,sex,address from user")
        List<User> findAll();
        
    2. 将接口注册到mybatis主配置文件中

      • <mappers>
            <mapper class="com.danny.dao.UserDao"/>
        </mappers>
        
  • 多表操作

    • 一对一查询

      • @Results({
                    @Result(column = "pid",property = "pid"),
                    @Result(column = "pname",property = "pname"),
                    @Result(column = "paddress",property = "paddress"),
                    @Result(column = "hire_date",property = "hireDate"),
                    @Result(property = "car",column = "pid",
                            one=@One(select = "com.offcn.dao.CarDao.findCarByPid",fetchType = FetchType.LAZY))
            })
            @Select("select pid,pname,paddress,hire_date from person where pid=#{pid}")
            Person findPersonCarByPid(long pid);
        
    • 一对多查询

      •  @Results({
                    @Result(column = "pid",property = "pid"),
                    @Result(column = "pname",property = "pname"),
                    @Result(column = "paddress",property = "paddress"),
                    @Result(column = "hire_date",property = "hireDate"),
                    @Result(property = "ordersList",column = "pid",
                            many=@Many(select = "com.offcn.dao.OrdersDao.findOrdersByPid"))
            })
            @Select("select pid,pname,paddress,hire_date from person where pid=#{pid}")
            Person findPersonOrdersByPid(long pid);
        

复杂关系注解映射

  • @Results 注解

    • 代替的是标签<resultMap>
    • 该注解中可以使用单个@Result 注解,也可以使用@Result 集合
    • @Results({@Result(), @Result()}) 或 @Results(@Result())
  • @Resutl 注解

    • 代替了<id>标签和<result>标签
    • @Result 中 属性介绍:
      • id 是否是主键字段
      • column 数据库的列名
      • property 需要装配的属性名
      • one 需要使用的@One 注解(@Result(one=@One)()))
      • many 需要使用的@Many 注解(@Result(many=@many)()))
  • @One 注解(一对一)

    • 代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。
    • @One 注解属性介绍:
      • select 指定用来多表查询的 sqlmapper
      • fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。。
    • 使用格式:
      • @Result(column=" “,property=”",one=@One(select=""))
  • @Many 注解(多对一)

    • 代替了<Collection>标签,是是多表查询的关键,在注解中用来指定子查询返回对象集合。
    • 注意:
      • 聚集元素用来处理“一对多”的关系。需要指定映射的 Java 实体类的属性,属性的 javaType
        (一般为 ArrayList)但是注解中可以不定义;
    • 使用格式:
      • @Result(property="",column="",many=@Many(select=""))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值