zoukankan      html  css  js  c++  java
  • 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>
    杂家不如专家,精益求精
  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/jimisun/p/7901377.html
Copyright © 2011-2022 走看看