• MyBatis基础入门


    1.MyBatis概述

    • MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
    • Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatement、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

    2.为什么要使用MyBatis(使用JDBC编程有哪些问题)?

    1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

    2. Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

    3. 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
    4. 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

    3.MyBatis架构

    1. MyBatis配置
      • SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息

      • mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载
    2. 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

    3. 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行

    4. mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
    5. Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

    6. Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

    7. Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor

    4.MyBatis入门

    创建Maven工程

    修改pom.xml导入MyBatis以及Junit和MySql驱动的jar包

    <dependencies>
            <!-- MySQL驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.29</version>
            </dependency>
    
            <!--junit -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <!-- mybatis -->
            <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
    </dependencies>

    classpath目录下创建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="development">
            <environment id="development">
                <!-- 使用jdbc事务管理 -->
                <transactionManager type="JDBC" />
                <!-- 数据库连接池 -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver" />
                    <property name="url"
                        value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
                    <property name="username" value="root" />
                    <property name="password" value="root" />
                </dataSource>
            </environment>
        </environments>
    
        <!-- 加载映射文件 -->
        <mappers>
            <mapper resource="User.xml" />
        </mappers>
    
    </configuration>

    创建测试数据库

    创建po类  ---Po类作为mybatis进行sql映射使用,po类通常与数据库表对应

    package pojo;

    import java.util.Date;

    public class User {

        private int id;
        private String username;// 用户姓名
        private String sex;// 性别
        private Date birthday;// 生日
        private String address;// 地址

    getter and setter方法......

        @Override
        public String toString() {
            return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
                    + address + "]";
        }      

    }

    创建sql映射文件User.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">
    <!-- namespace:命名空间,做sql隔离 -->
    <mapper namespace="test">
    
        <!-- 
        id:sql语句唯一标识
        parameterType:指定传入参数类型
        resultType:返回结果集类型
        #{}占位符:起到占位作用,如果传入的是基本类型(string,long,double,int,boolean,float等),那么#{}中的变量名称可以随意写.
         -->
        <select id="findUserById" parameterType="java.lang.Integer" resultType="cn.itheima.pojo.User">
            select * from user where id=#{id}
        </select>
        
        <!-- 
        如果返回结果为集合,可以调用selectList方法,这个方法返回的结果就是一个集合,所以映射文件中应该配置成集合泛型的类型
        ${}拼接符:字符串原样拼接,如果传入的参数是基本类型(string,long,double,int,boolean,float等),那么${}中的变量名称必须是value
        注意:拼接符有sql注入的风险,所以慎重使用
         -->
        <select id="findUserByUserName" parameterType="java.lang.String" resultType="cn.itheima.pojo.User">
            select * from user where username like '%${value}%'
        </select>
        
        <!-- 
        #{}:如果传入的是pojo类型,那么#{}中的变量名称必须是pojo中对应的属性.属性.属性.....
        如果要返回数据库自增主键:可以使用select LAST_INSERT_ID()
         -->
        <insert id="insertUser" parameterType="cn.itheima.pojo.User" >
            <!-- 执行 select LAST_INSERT_ID()数据库函数,返回自增的主键
            keyProperty:将返回的主键放入传入参数的Id中保存.
            order:当前函数相对于insert语句的执行顺序,在insert前执行是before,在insert后执行是AFTER
            resultType:id的类型,也就是keyproperties中属性的类型
            -->
            <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
                select LAST_INSERT_ID()
            </selectKey>
            insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
        </insert>
        
        <delete id="delUserById" parameterType="int">
            delete from user where id=#{id}
        </delete>
        
        <update id="updateUserById" parameterType="cn.itheima.pojo.User">
            update user set username=#{username} where id=#{id}
        </update>
    </mapper>

    加载映射文件 --mybatis框架需要加载映射文件,将User.xml添加在SqlMapConfig.xml

    <!-- 加载映射文件 -->
        <mappers>
            <mapper resource="User.xml" />
        </mappers>

    创建测试类UserTest进行测试

    查询单个User对象

    @Test
        public void test1() throws IOException {
            // 核心配置文件
            String resource = "SqlMapConfig.xml";
            // 通过流将核心配置文件加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 通过配置文件创建会话工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过会话工厂获取会话
            SqlSession openSession = factory.openSession();
            // 通过会话执行sql 第一个参数是名称空间+SqlID 第二个参数表示sql执行需要的参数
            User user = openSession.selectOne("test.findUserById", 1);
            System.out.println(user.toString());
            // 关闭会话
            openSession.close();
    
        }

    通过username进行模糊查询

    @Test
        public void test2() throws IOException {
            // 核心配置文件
            String resource = "SqlMapConfig.xml";
            // 通过流将核心配置文件加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 通过配置文件创建会话工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过会话工厂获取会话
            SqlSession openSession = factory.openSession();
            // 调用User.xml中的魔化查询方法 返回集合
            List<User> selectList = openSession.selectList("test.findUserByName", "张");
            // 循环结果
            System.out.println(selectList.size());
            for (User user : selectList) {
                System.out.println(user.toString());
            }
            // 关闭会话
            openSession.close();
        }

    添加一条User用户到数据库

    @Test
        public void test3() throws IOException {
            // 核心配置文件
            String resource = "SqlMapConfig.xml";
            // 通过流将核心配置文件加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 通过配置文件创建会话工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过会话工厂获取会话
            SqlSession openSession = factory.openSession();
            // 创建需要插入的User对象
            User user = new User();
            user.setUsername("Jimisun");
            user.setSex("1");
            user.setAddress("北京");
            System.out.println("====插入前的User的id=" + user.getId());
            // 会话调用插入的sql
            openSession.insert("test.insertUser", user);
            // 默认mybatis自动开启事务,需要手动提交事务
            openSession.commit();
            System.out.println("====插入后的User的id=" + user.getId());
            // 关闭会话
            openSession.close();
        }

    删除一条记录

    @Test
        public void test4() throws IOException {
            // 核心配置文件
            String resource = "SqlMapConfig.xml";
            // 通过流将核心配置文件加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 通过配置文件创建会话工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过会话工厂获取会话
            SqlSession openSession = factory.openSession();
            // 会话执行sql操作
            openSession.delete("test.deleteUserById", 1);
            // 提交事务
            openSession.commit();
            // 关闭会话
            openSession.close();
        }

    更新一条记录

    @Test
        public void test5() throws Exception {
            // 核心配置文件
            String resource = "SqlMapConfig.xml";
            // 通过流将核心配置文件加载进来
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 通过配置文件创建会话工厂
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过会话工厂获取会话
            SqlSession openSession = factory.openSession();
            //创建User对象
            User user = new User ();
            user.setId(1);
            user.setUsername("王麻子");
            openSession.update("test.updateByUserId", user);
            //提交事务
            openSession.commit();
            //关闭会话
            openSession.close();
    
        }

     5.使用MyBatis的开发方法

    • 原生Dao方法
      • UserDao  接口
      • UserDaoImpl  实现类
        • findUserById()  -----方法内使用MyBatis框架进行操作
          // 核心配置文件
                  String resource = "SqlMapConfig.xml";
                  // 通过流将核心配置文件加载进来
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  // 通过配置文件创建会话工厂
                  SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
                  // 通过会话工厂获取会话
                  SqlSession openSession = factory.openSession();
                  // 通过会话执行sql 第一个参数是名称空间+SqlID 第二个参数表示sql执行需要的参数
                  User user = openSession.selectOne("test.findUserById", 1);
                  System.out.println(user.toString());
                  // 关闭会话
                  openSession.close();
    • Mapper接口开发    ----Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
      • 开发规范
        • Mapper.xml文件中的namespace与mapper接口的类路径相同。

        • Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
        • Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

        • Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

      • 开发目录
        • UserDao   接口 遵循上面规则
        • UserServiceImpl直接调用
              @Test
              public void testFindUserById() throws Exception{
                  SqlSession openSession = factory.openSession();
                  //通过getMapper方法来实例化接口
                  UserMapper mapper = openSession.getMapper(UserMapper.class);
                  
                  User user = mapper.findUserById(1);
                  System.out.println(user);
              }

     6.SqlMapConfig.xml配置文件

    • properties(属性) 常用于加载配置文件
      <properties resource="db.properties"></properties>
      <environments default="development">
              <environment id="development">
              <!-- 使用jdbc事务管理-->
              <transactionManager type="JDBC" />
              <!-- 数据库连接池-->
              <dataSource type="POOLED">
                  <property name="driver" value="${jdbc.driver}" />
                  <property name="url" value="${jdbc.url}" />
                  <property name="username" value="${jdbc.username}" />
                  <property name="password" value="${jdbc.password}" />
              </dataSource>
              </environment>
      </environments>
    • typeAliases(类型别名)

      <typeAliases> 
              <!-- 定义单个pojo类别名
              type:类的全路劲名称
              alias:别名
               -->
              <typeAlias type="cn.itheima.pojo.User" alias="user"/> 
              
              <!-- 使用包扫描的方式批量定义别名 
              定以后别名等于类名,不区分大小写,但是建议按照java命名规则来,首字母小写,以后每个单词的首字母大写
              -->
              <package name="cn.itheima.pojo"/>
          </typeAliases>
    • mappers(映射器)

      • 相对于类路径的资源
        <mapper resource="sqlmap/User.xml" />
      • 使用mapper接口开发
        <mapper class="cn.redrat.mybatis.mapper.UserMapper"/>
      • 注册指定包下所有的mapper接口
        <package name="cn.redrat.mybatis.mapper"/>
        • 注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。

    7.输入映射和输出映射

    • Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
      • parameterType(输入类型)

        • 传递基本类型包含String
        • 传递pojo对象
        • 传递vo对象
      • resultType(输出类型)

        • 返回pojo类型
        • 返回集合
        • 返回基本类型包含String

    8.动态Sql --通过mybatis提供的各种标签方法实现动态拼接sql

    • if
      <!-- 传递pojo综合查询用户信息   注意要做不等于空字符串校验-->
          <select id="findUserList" parameterType="user" resultType="user">
              select * from user 
              where 1=1 
              <if test="id!=null">
              and id=#{id}
              </if>
              <if test="username!=null and username!=''">
              and username like '%${username}%'
              </if>
      </select>
    • where
      <select id="findUserList" parameterType="user" resultType="user">
              select * from user 
              <where>
              <if test="id!=null and id!=''">
              and id=#{id}
              </if>
              <if test="username!=null and username!=''">
              and username like '%${username}%'
              </if>
              </where>
      </select

       where标签的作用可以去掉sql语句中的where 1=1 并自动处理第一个 and

    • foreach
      <select id="findUserByIds" parameterType="cn.redrat.pojo.QueryVo" resultType="cn.redrat.pojo.User">
              select * from user
              <where>
                  <if test="ids != null">
                      <!-- 
                      foreach:循环传入的集合参数
                      collection:传入的集合的变量名称
                      item:每次循环将循环出的数据放入这个变量中
                      open:循环开始拼接的字符串
                      close:循环结束拼接的字符串
                      separator:循环中拼接的分隔符
                       -->
                      <foreach collection="ids" item="id" open="id in (" close=")" separator=",">
                          #{id}
                      </foreach>
                  </if>
              </where>
          </select>

    9.MyBatis关联查询核心示例

    • 一对一查询
      <!-- 一对一:自动映射 -->
          <select id="findOrdersAndUser1" resultType="cn.redrat.pojo.CustomOrders">
              select a.*, b.id uid, username, birthday, sex, address 
              from orders a, user b 
              where a.user_id = b.id
          </select>
          
          <!-- 一对一:手动映射 -->
          <!-- 
          id:resultMap的唯一标识
          type:将查询出的数据放入这个指定的对象中
          注意:手动映射需要指定数据库中表的字段名与java中pojo类的属性名称的对应关系
           -->
          <resultMap type="cn.redrat.pojo.Orders" id="orderAndUserResultMap">
              <!-- id标签指定主键字段对应关系
              column:列,数据库中的字段名称
              property:属性,java中pojo中的属性名称
               -->
              <id column="id" property="id"/>
              
              <!-- result:标签指定非主键字段的对应关系 -->
              <result column="user_id" property="userId"/>
              <result column="number" property="number"/>
              <result column="createtime" property="createtime"/>
              <result column="note" property="note"/>
              
              <!-- 这个标签指定单个对象的对应关系 
              property:指定将数据放入Orders中的user属性中
              javaType:user属性的类型
              -->
              <association property="user" javaType="cn.redrat.pojo.User">
                  <id column="uid" property="id"/>
                  <result column="username" property="username"/>
                  <result column="birthday" property="birthday"/>
                  <result column="sex" property="sex"/>
                  <result column="address" property="address"/>
              </association>
          </resultMap>
          <select id="findOrdersAndUser2" resultMap="orderAndUserResultMap">
              select a.*, b.id uid, username, birthday, sex, address 
              from orders a, user b 
              where a.user_id = b.id
          </select>
    • 一对多
      <resultMap type="cn.redrat.pojo.User" id="userAndOrdersResultMap">
              <id column="id" property="id"/>
              <result column="username" property="username"/>
              <result column="birthday" property="birthday"/>
              <result column="sex" property="sex"/>
              <result column="address" property="address"/>
              
              <!-- 指定对应的集合对象关系映射
              property:将数据放入User对象中的ordersList属性中
              ofType:指定ordersList属性的泛型类型
               -->
              <collection property="ordersList" ofType="cn.redrat.pojo.Orders">
                  <id column="oid" property="id"/>
                  <result column="user_id" property="userId"/>
                  <result column="number" property="number"/>
                  <result column="createtime" property="createtime"/>
              </collection>
          </resultMap>
          <select id="findUserAndOrders" resultMap="userAndOrdersResultMap">
              select a.*, b.id oid ,user_id, number, createtime 
              from user a, orders b where a.id = b.user_id
          </select>
    杂家不如专家,精益求精
  • 相关阅读:
    node连接数据库(express+mysql)
    Apache与Tomcat有什么关系和区别
    tomcat部署简单的html静态网页
    Vue项目webpack打包部署到服务器
    windows下vue+webpack前端开发环境搭建及nginx部署
    DIV 边框重叠 像素变粗 解决办法
    基于iscroll实现下拉和上拉刷新
    css图片居中(水平居中和垂直居中)
    nodejs分页类
    事件--键盘事件
  • 原文地址:https://www.cnblogs.com/jimisun/p/7901377.html
Copyright © 2020-2023  润新知