【MyBatis】MyBatis的DAO代理、输入、输出(笔记二)

24 篇文章 1 订阅
5 篇文章 0 订阅

【MyBatis】MyBatis学习笔记二(DAO代理、输入、输出)

1、DAO代理

1.1 MyBatis 提供代理
  • MyBatis创建Dao接口的实现类对象,完成对sql语句的执行。MyBatis创建一个对象代替dao实现类的功能。
1.2 使用MyBatis的要求

1)mapper文件中的namespace一定为dao接口的全限定名称。

2)mapper文件中SQL标签的id是dao接口的方法名。

3)mapper文件与dao接口必须在同一个目录下。

4)mapper文件与dao接口的文件名必须一致。

5)mapper文件中标签的parameterType属性值与dao接口中的方法参数类型完全一致。

6)在mybatis-config.xml文件中注册mapper文件时,使用 class=接口的完全限定名称。

1.3 MyBatis代理实现方式
  • 使用SqlSession对象的方法 getMapper(dao.class)

  • 例(StudentDao接口):

    package com.Etui.dao;
    import com.Etui.entity.Student;
    public interface StudentDao {
        // 查询一条记录
        Student selectStudentById(Integer id);
    }
    

    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.Etui.dao.StudentDao">
    
        <!-- 根据id查询Student记录 -->
        <select id="selectStudentById" resultType="com.Etui.entity.Student">
            select * from student where id = #{id}
        </select>
    </mapper>
    
  • 通过MyBatis代理实现的查询功能:

    import com.Etui.dao.StudentDao;
    import com.Etui.entity.Student;
    import com.Etui.uitls.MyBatisUtil;
    import org.apache.ibatis.session.SqlSession;
    
    public void testSelectStudentById() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        // 查询id为1009的学生信息
        Student student = dao.selectStudentById(1009);
        System.out.println(student);
        // 关闭SqlSession对象
        session.close();
    }
    

2、参数

  • 通过java程序把数据传入到mapper文件的SQL语句中,参数主要指dao接口方法的形参。
2.1 parameterType
  • parameterType:表示参数的类型,指定dao方法的形参数据类型。这个形参的数据类型是给mybatis使用的。mybatis在给SQL语句的参数赋值时使用。等同于JDBC中prepareStatement.setXXX(位置,值)。

  • 当parameterType的类型是简单类型(8中基本(封装) + String), 则 #{} 可随意填写,如:

    <select id="getById" parameterType="int" resultType="users">  ===>入参类型是简单类型
        select id,username,birthday,sex,address
        from users
        where id=#{xxx}  ===>随便写
    </select>  
    
  • 当parameterType的类型是实体类的类型(如 Student类),则 #{} 内只能是类中的成员变量的名称,而且区分大小写。如:

    <insert id="insert" parameterType="Student" >  ===>入参是实体类
        insert into users (id, name, email, age) values(#{id},#{name},#{email},#{age})  ==>成员变量名称
    </insert>
    
    <!--  
    	Student实体类如下:
    
    public class Student {
        private Integer id;
        private String name;
        private String email;
        private Integer age;
    
    	getter……
    	setter……
    	……………………
    }
    
    -->
    
2.2 当dao接口方法含一个简单参数时
  • dao接口如下:

    // dao接口的函数,含有一个Integer类型的参数
    // 查询一条记录
    Student selectStudentById(Integer id);
    
  • mapper如下:

    <!-- 根据id查询Student记录 -->
    <select id="selectStudentById" resultType="com.Etui.entity.Student">
        select id,name,email,age from student where id = #{id}
    </select>
    
  • 测试代码如下:

    public void testSelectStudentById() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Student student = dao.selectStudentById(1009);
        System.out.println(student);
        // 关闭SqlSession对象
        session.close();
    }
    
2.3 当dao接口方法含多个简单类型参数时
  • dao接口方法如下:

    /*
        多个简单类型的参数
        使用@Param命名参数,注解是mybatis提供的
        位置:在形参定义的前面
        属性:value 自定义的参数名称,“value = ”可省略
    */
    //    List<Student> selectByNameOrAge(@Param(value = "myName") String name, @Param(value = "myAge") Integer age);
        List<Student> selectByNameOrAge(@Param("myName") String name, @Param("myAge") Integer age);
    
  • mapper如下:

    <!--
        多个简单类型的参数
        当使用了@Param命名后,例如@Param(“myName”)
        在mapper中,使用#{命名的参数}, 例如 #{myName}
     -->
    <select id="selectByNameOrAge" resultType="com.Etui.entity.Student">
        select * from student where name = #{myName} or age = #{myAge}
    </select>
    
  • 测试代码如下:

    public void testSelectByNameOrAge() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        List<Student> students = dao.selectByNameOrAge("刻晴", 18);
        students.forEach(System.out::println);
        session.close();
    }
    
2.4 当dao接口方法使用一个对象作为参数时
  • dao方法如下:

    // 插入一条记录, 以Student对象作为参数
    Integer insertStudent(Student student);
    
  • mapper如下:

    <!-- 插入一条记录(parameterType为参数类型) -->
    <!--
        此处参数为一个Student对象
        此时下方SQL语句中的占位符(id/name/email/age)均为Student对象中的属性。
     -->
    <insert id="insertStudent" parameterType="com.Etui.entity.Student">
        insert into student(id,name,email,age) values(#{id}, #{name}, #{email}, #{age})
    </insert>
    
  • 测试代码:

    public void testInsertStudent() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Student student = new Student(null, "香菱", "xiangling@qq.com", 19);
        Integer result = dao.insertStudent(student);
        System.out.println(result == 1 ? "添加成功!" : "添加失败!");
        // 提交事务
        session.commit();
        session.close();
    };
    
2.5 多个简单类型参数,使用“位置”
  • dao方法如下:

    // 通过位置获取参数值
    List<Student> selectStudentByPosition(String name, Integer age);
    
  • mapper如下:

    <!--
        使用位置获取参数值,dao接口方法是多个简单类型的参数
        语法: #{arg0} , #{arg1} ……
    -->
    <select id="selectStudentByPosition" resultType="com.Etui.entity.Student">
        select * from student where name = #{arg0} or age = #{arg1}
    </select>
    
  • 测试代码:

    public void testSelectStudentByPosition() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        List<Student> students = dao.selectStudentByPosition("刻晴", 18);
        students.forEach(System.out::println);
        session.close();
    }
    
2.6 当参数为Map时
  • dao方法如下:

    // 通过Map对象获取参数值
    List<Student> selectStudentByMap(Map<String, Object> data);
    
  • mapper如下:

    <!--
        使用Map对象传递参数
        在mapper文件中,获取map的值,是通过key获取的,语法:#{key}
     -->
    <select id="selectStudentByMap" resultType="com.Etui.entity.Student">
        select * from student where name = #{name} or age = #{age}
    </select>
    
  • 测试代码:

    public void testSelectStudentByMap() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        // 创建Map对象并添加数据
        Map<String, Object> data = new HashMap<>();
        data.put("name", "刻晴");
        data.put("age", 22);
        List<Student> students = dao.selectStudentByMap(data);
        students.forEach(System.out::println);
        session.close();
    }
    

3、#{} 和 ${} 的区别

3.1 #{} 占位符的特点
  • 使用prepareStatement对象执SQL语句,效率高。
  • 使用prepareStatement对象,能避免SQL注入,SQL语句执行更安全。
  • #{} 常常作为列值使用,位于等号的右侧,#{}位置的值是和数据类型有关的。
3.2 ${} 的特点
  • 使用Statemet对象执行SQL语句,效率低。
  • ${} 占位符的值,使用的字符串连接方式,有SQL注入的风险。有代码安全问题。
  • ${} 数据是原样使用的,不会区分数据类型。
  • ${} 常用作 表名 或 列名 ,在能保证数据安全的情况下使用。

4、封装MyBatis输出结果

4.1 resultType
  • resultType:执行SQL得到ResultSet转换的类型,使用类型的完全限定名或别名。
  • 如果返回的是集合,应当设置为集合包含的类型,而不是集合本身。
  • resultType与resultMap不能同时使用
4.1.1 resultType为简单类型(以int为例)
  • dao接口方法如下:

    // 查询表中的记录数
    long getCounts();
    
  • mapper如下:

    <select id="getCounts" resultType="java.lang.Long">
        select count(*) from student
    </select>
    
  • 测试代码如下:

    @Test
    public void testGetCounts() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Long result = dao.getCounts();
        System.out.println("counts = " + result);
        // 关闭SqlSession对象
        session.close();
    }
    
4.1.2 resultType为对象类型(以Student类为例)
  • dao接口方法如下:

    // 查询一条记录
    Student selectStudentById(Integer id);
    
  • mapper如下:

    <!-- 根据id查询Student记录 -->
    <select id="selectStudentById" resultType="com.Etui.entity.Student">
        select * from student where id = #{id}
    </select>
    
  • 测试代码如下:

    @Test
    public void testSelectStudentById() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Student student = dao.selectStudentById(1009);
        System.out.println(student);
        // 关闭SqlSession对象
        session.close();
    }
    
4.1.3 resultType为Map类型
  • SQL的查询结果为Map的key和value。推荐使用Map<Object, Object>。

  • 注:Map作为接口返回值,SQL语句的查询结果最多只能有一条记录。

  • dao接口如下:

    // 当返回值为Map时
    Map<Object, Object> selectMap(Integer id);
    
  • mapper如下:

    <!--
        执行SQL得到一个Map结构数据,mybatis执行SQL,把ResultSet转换为Map
        sql执行结果,列名叫做map的key, 列值为map的value。
        SQL执行得到是一个记录,转换为map结构是正确的
    
        dao接口返回是一个map, SQL语句最多能获取一条记录,多行则报错
    -->
    <select id="selectMap" resultType="java.util.HashMap">
        select * from student where id = #{id}
    </select>
    
  • 测试代码:

    @Test
    public void testSelectMap() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao dao = session.getMapper(StudentDao.class);
        Map<Object, Object> data = dao.selectMap(1009);
    
        System.out.println("name = " + data.get("name"));
        System.out.println("age = " + data.get("age"));
        // 关闭SqlSession对象
        session.close();
    }
    
4.2 resultMap
  • resultMap: 结果映射。自定义别名和java对象属性的对应关系。常用在列名和属性名不同的情况。使用方法如下:

    • 先定义resultMap标签,指定列名和属性名称的对应关系。
    • 在select标签时用resultMap属性,指定上面定义resultMap的id值。
  • 实例:

    • 已知Customer类与Student类含有相同的属性和方法,但属性名和方法名不同,如下:

      package com.Etui.entity;
      
      public class Customer {
          private Integer sId;
          private String sName;
          private String sEmail;
          private Integer sAge;
      	……
          ……
          ……   
      }
      
    • Student类如下:

      package com.Etui.entity;
      
      public class Student {
          private Integer id;
          private String name;
          private String email;
          private Integer age;
      	……
          ……
          ……   
      }
      
    • StudentDao接口中的方法如下:

      // 查询一条记录
      Customer selectStudentById2(Integer id);
      
    • StudentDao.xml文件中的对应SQL如下:

      <!-- 使用resultMap定义列和属性的关系 -->
      <!-- 定义resultMap
              id:给resultMap的映射关系起个名称,唯一值
              type:java类型的全限定名称
              当类名和属性名相同时不用定义
       -->
      <resultMap id="customMap" type="com.Etui.entity.Customer">
          <!-- 定义列名和属性名的对应 -->
          <!-- 主键类型使用id标签 -->
          <id column="id" property="sId" />
          <!-- 非主键类型使用result标签 -->
          <result column="name" property="sName" />
          <result column="email" property="sEmail" />
          <result column="age" property="sAge" />
      </resultMap>
      <!-- 使用resultMap属性,指定映射关系的id -->
      <select id="selectStudentById2" resultMap="customMap">
          select * from student where id = #{id}
      </select>
      
    • 测试代码如下:

      @Test
      public void testSelectStudentById2() {
          SqlSession session = MyBatisUtil.getSqlSession();
          StudentDao dao = session.getMapper(StudentDao.class);
          Customer customer = dao.selectStudentById2(1009);
          System.out.println(customer);
          // 关闭SqlSession对象
          session.close();
      }
      
    • 运行结果如下:
      在这里插入图片描述

    • 由查询结果可以看出,结果为Customer类的实例,且与Student类不同属性名的属性值未被赋值为空。

4.3 列名和java对象属性名不一样的解决方式
  • 1、通过resultMap实现。

  • 2、通过SQL语句中的别名实现。实现与上文案例相同的功能,mapper如下:

    • <!-- 使用列别名,解决列名和属性名不同的问题 -->
      <select id="selectStudentById3" resultType="com.Etui.entity.Customer">
          select id sId, name sName, email sEmail, age Sage from student where id = #{id}
      </select>
      
4.4 模糊查询(like)
  • 模糊查询的实现有两种方式,一是java代码中给查询数据加上”%“;二是在mapper文件SQL语句的条件位置加上”%“。

  • 案例如下,查询“网”姓同学:

    • dao接口方法如下:

      // 查询指定姓氏的同学(方式一)
      List<Student> selectByLike1(String lastname);
      // 查询指定姓氏的同学(方式二)
      List<Student> selectByLike2(String lastname);
      
    • 方式一mapper如下:

      <!-- 模糊查询(方式一) -->
      <select id="selectByLike1" resultType="com.Etui.entity.Student">
          select * from student where name like "%" #{name} "%"
      </select>
      
    • 方式一测试代码如下:

      @Test
      public void testSelectByLike1() {
          SqlSession session = MyBatisUtil.getSqlSession();
          StudentDao dao = session.getMapper(StudentDao.class);
          List<Student> students = dao.selectByLike1("王");
          students.forEach(System.out::println);
          // 关闭SqlSession对象
          session.close();
      }
      
    • 方式二mapper如下:

      <!-- 模糊查询(方式二) -->
      <select id="selectByLike2" resultType="com.Etui.entity.Student">
          select * from student where name like #{name}
      </select>
      
    • 方式二测试代码如下:

      @Test
      public void testSelectByLike2() {
          SqlSession session = MyBatisUtil.getSqlSession();
          StudentDao dao = session.getMapper(StudentDao.class);
          String lastname = "%王%";
          List<Student> students = dao.selectByLike2(lastname);
          students.forEach(System.out::println);
          // 关闭SqlSession对象
          session.close();
      }
      

Over!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值