一文带你快速搭建框架(二)

203 阅读3分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

3.SQL语句中参数的获取

(1)获取方式

  • MyBatis获取参数值的两种方式: ${}和#{}

  • ${}的本质是字符串拼接,#{}的本质是占位符赋值

  • ${}方式会将参数原原本本拼接入SQL语句中,如果参数是字符串类型的需要手动加上引号

    `${参数}`
    
  • #{}的方式会自动加上引号,如果是字符串类型的参数无需手动加上引号

    #{参数}
    

(2)参数类型

  • 单个字面量类型的参数

    • 字面量是指基本数据类型以及包装类还有自定义类等

    • 获取方式

      <select id="getUserByUsername" resultType="User">
          select * from t_user where username=#{username}
      </select>
      
    • 此时获取参数时花括号里边的参数名不做要求,可以是随意的名称,如果使用${}的方式记得加引号

  • 多个字面量类型的参数

    • 若mapper接口中的方法参数为多个时,MyBatis会自动将这些参数放在一个map集合中,此时参数名不能是随意的名称

    • 这个map集合存放参数的形式是arg0,arg1...为map中的键,参数值为map中的值;还有param1,param2...为map中的键,参数值为map值的值

    • arg和param是同时存在于同一个map中的,在SQL语句获取参数时只需指定这些键的名称即可

    • 获取方式

      <!--arg的方式-->
      <select id="checkLogin" resultType="User">
          select * from t_user where username = #{arg0} and password = #{arg1}
      </select>
      <!--param的方式-->
      <select id="checkLogin" resultType="User">
              select * from t_user where username = #{param1} and password = #{param2}
      </select>
      
    • 如果使用${}的方式记得加引号

  • map集合类型的参数

    • 为了在SQL语句中指定一些有意义的参数名,我们可以自己提供一个map集合,自定义一些键的名称即可

    • 通过自定义键的名称,我们在SQL语句里就可以使用自定义的参数名了

    • 比如,这个自定义的map集合可以是{("username","参数值"),("password","参数值")}

    • 获取方式

      <select id="checkLoginByMap" resultType="User">
          select * from t_user where username = #{username} and password = #{password}
      </select>
      
    • 如果使用${}的方式记得加引号

  • 使用@Param注解标识的参数

    • 如果每次使用多个参数时都要自定义map集合就太麻烦了,所以可以通过使用@Param注解在映射方法的形参中指定好参数名

    • 比如,这个映射方法可以是

      User getUserByParam(@Param("username") String username,@Param("password") String password);
      
    • 获取方式

      <select id="checkLoginByParam" resultType="User">
          select * from t_user where username = #{username} and password = #{password}
      </select>
      
    • 使用这种注解就可以方便获取参数了,如果使用${}的方式记得加引号

  • 实体类型的参数

    • 如果映射方法的形参是一个实体类型时,可以通过访问实体类对象中的属性名获取属性值

    • 比如,这个实体类可以是

      public class User {
          private Integer id;
          private String username;
          private String password;
          private Integer age;
          private String gender;
          private String email;
          //省略有参、无参构造方法以及toString()方法
          public Integer getId() {
              return id;
          }
          public void setId(Integer id) {
              this.id = id;
          }
          public String getUsername() {
              return username;
          }
          public void setUsername(String username) {
              this.username = username;
          }
          public String getPassword() {
              return password;
          }
          public void setPassword(String password) {
              this.password = password;
          }
          public Integer getAge() {
              return age;
          }
          public void setAge(Integer age) {
              this.age = age;
          }
          public String getGender() {
              return gender;
          }
          public void setGender(String gender) {
              this.gender = gender;
          }
          public String getEmail() {
              return email;
          }
          public void setEmail(String email) {
              this.email = email;
          }
      }
      
    • 获取方式

      <insert id="insertUser">
          insert into t_user value(null,#{username},#{password},#{age},#{gender},#{email})
      </insert>
      
    • 如果使用${}的方式记得加引号

  • 总结

    • 上面所说的五种参数类型实际上可以分成两种类型,一种是使用 @Param注解一种是使用实体类
    • 就是说不论单个参数或者多个参数,都用注解的方式,如果是实体类那就用实体类属性的方式

4.各种SQL操作

  • 查询一个实体类对象

    映射方法:

    User getUserById(@Param("id") int id);
    

    映射文件:

    <select id="getUserById" resultType="User">
        select * from t_user where id = #{id}
    </select>
    
  • 查询一个List集合

    映射方法:

    List<User> getAllUser();
    

    映射文件:

    <select id="getAllUser" resultType="User">
        select * from t_user
    </select>
    

    注意:当查询的数据为多条时,不能使用实体类作为返回值,否则会抛出异常 TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值

  • 查询单个数据

    映射方法:

    int getCount();
    

    映射文件:

    <select id="getCount" resultType="java.lang.Integer">
        select count(id) from t_user
    </select>
    
  • 查询一条数据到map集合

    映射方法:

    Map<String,Object> getUserToMap(@Param("id") int id);
    

    映射文件:

    <select id="getUserToMap" resultType="java.util.Map">
        select * from t_user where id = #{id}
    </select>
    

    注意:将一条数据查询到map集合中时,map的键是表中的字段名,map的值是表中数据

  • 查询多条数据到map集合

    • 方式一

      映射方法:

      List<Map<String,Object>> getAllUserToMap();
      

      映射文件:

      <select id="getAllUserToMap" resultType="java.util.Map">
          select * from t_user
      </select>
      
    • 方式二

      映射方法:

      @MapKey("id")
      Map<String,Object> getAllUserToMap();
      

      映射文件:

      <select id="getAllUserToMap" resultType="java.util.Map">
          select * from t_user
      </select>
      
    • 注意

      • 方式一中每条查出来的数据都对应一个Map集合,然后再利用List集合将这些Map集合组织起来

      • 方式二中每条查出来的数据都存放在一个Map集合中,但是这个Map集合的键由映射方法上方的@MapKey注解指定,而Map集合的值又是另外一个Map集合,作为值的Map集合中键对应表中字段名,值对应表中数据

      • 方式二范例

        {
        1={password=123456, sex=男, id=1, age=23, username=admin},
        2={password=123456, sex=男, id=2, age=23, username=张三},
        3={password=123456, sex=男, id=3, age=23, username=张三}
        }
        
  • 模糊查询

    映射方法:

    List<User> getUserByLike(@Param("mohu") String mohu);
    

    映射文件:

    <select id="getUserByLike" resultType="User">
        <!--方式1-->
        select * from t_user where username like '%${mohu}%'
        <!--方式2-->
        select * from t_user where username like concat("%",#{mohu},"%")
        <!--方式3-->
        select * from t_user where username like "%"#{mohu}"%"
    </select>
    

    注意:不能使用like '%#{mohu}%'的方式,因为#{}会被解析成?,这个问号会被当成字符串的一部分造成参数获取失败

  • 批量删除

    映射方法:

    void deleteSomeUser(@Param("ids") String ids);
    

    映射文件:

    <delete id="deleteSomeUser">
        delete from t_user where id in(${ids})
    </delete>
    

    注意:这里获取参数的方式是${},因为#{}会自动添加引号,如果使用#{}的方式会造成SQL语句解析成delete from t_user where id in('ids')从而报错

  • 动态设置表名

    映射方法:

    List<User> getUserList(@Param("table") String table);
    

    映射文件:

    <select id="getUserList" resultType="User">
        select * from ${table}
    </select>
    

    注意:这里使用${}是因为使用#{}时会自动添加引号,而表名不允许添加表名

  • 执行添加功能时获取自增的主键

    映射方法:

    void insertUser(User user);
    

    映射文件:

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email})
    </insert>
    

    测试方法:

    @Test
    public void testInsertUser(){
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
        User user = new User(null,"李晨","1234567",46,"男","lichen@qq.com");
        mapper.insertUser(user);
        System.out.println(user);//在这一步中打印出的User对象中可以看到自增的id,如果配置文件中不使用useGeneratedKeys和keyProperty,则id仍然是null
    }
    

    注意:这里的useGeneratedKeys设置使用自增主键为true,keyProperty是将获取的主键值赋给实体对象中的某个属性。这样,在添加这个实体对象后,自增的主键也能在实体对象中获得,而不需要进行查询