JavaWeb-Mybatis基础

5.3 Mybatis基础操作

5.3.1 根据主键删除
  • SQL语句

    delete from emp where id = 17;

  • 接口方法

    @Delete(“delete from emp where id = #{id}”) ->参数占位符

    public void delete(Integer id);

  • 注意事项:如果mapper接口方法形参只有一个普通类型的参数,#{…}里面的属性名可以随便写,如:#{id}、#{value}。

mybatis日志
#在application.properties中添加如下配置:

#配置mybatis的日志信息,指定输出到控制台

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

#我们不需要记住全部字段,只需记住关键字就行。我们在IDEA中输入mybatis.log,IDEA会联想提示。
@Delete("delete from emp where id = #{id}") 
public void delete(Integer id);

//我们再次运行上面的方法时:
 @Autowired
    private EmpMapper empMapper;

    @Test
    public void testDelete(){
        empMapper.delete(16);
    }

/*
其中两个==>所在的语句称为预编译SQL。而?是预编译SQL中的参数占位符


*/

在这里插入图片描述

预编译SQL

预编译SQL的优势:

  • 性能更高

    Java执行MySQL语句时需要走四个步骤:SQL语法检查->优化SQL->编译SQL->执行SQL

在这里插入图片描述

当我们执行下面的语句时,由于这三句是不同的语句,在SQL中没有缓存,因此上面的四个步骤都要走一边,而且要走三遍

在这里插入图片描述

而我们执行下面的语句时:

在这里插入图片描述

第一次编译时,SQL会将 delete from emp where id = ?;这句放入缓存中,然后将1以实参的形式进行编译、执行。

但第二次时,由于SQL缓存中有 delete from emp where id = ?;,所以第二次可以直接将2代入执行。第三次也是如此。

所以上面的要编译3次,而下面的只需要编译1次。

  • 更安全(防止SQL注入)

    SQL注入:通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

    比如我们要登录一个界面,当我们输入正确的账号和密码时:

    在这里插入图片描述

    至于能否登录成功,一般来说只需要账号密码跟服务器里中能查询到数据就行,而如果这种查询语句为:

    select count(*) from emp where username = 'zhangwuji' and password = '123456';
    -- 只要查询结果不为0,那么就可以登录
    

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    然后进行SQL注入操作

    -- 如果将密码修改为'or '1'='1
    select count(*) from emp where username = 'xxxxx' and password = ''or '1'='1';
    -- 那么这条语句将永远正确,也就是能够登录成功,这就是SQL注入
    

    但是如果查询语句改为预编译MySQL

    select count(*) from emp where username = ? and password = ?;
    -- 这里会把输入的内容当作字符串处理,这样就不会修改mysql语句了。也就是可以阻止MySQL注入
    
  • 写出预编译SQL语句,就是用参数占位符实现的。

    /*
    1.#{...}
    执行SQL时,会将#{...}替换成?,生成预编译SQL,会自动设置参数值
    使用时机:参数传递,都用#{...}
    
    2.${...}
    拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
    使用时机:如果对表名、列表进行动态设置时使用(用得比较少)。
    
    两者的区别是,${...}直接将?替换成了实参。#{...}则是间接。
    */
    

在这里插入图片描述

5.3.2 新增
  • SQL语句

    insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
                values('伊吕波','168','1','1.jpg','1','2000-01-01',1,now(),now());
    
  • 接口方法

    -- empMapper
    @Insert("insert into emp(username,  name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
             " values(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
        public void insert(Emp emp);
    
    
    -- Test
     public void testInsert(){
            Emp emp = new Emp();
            emp.setUsername("伊吕波");
            emp.setName("168");
            emp.setImage("1.jpg");
            emp.setGender(((short)1));
            emp.setJob((short) 1);
            emp.setEntrydate(LocalDate.of(2000,1,1));
            emp.setCreateTime(LocalDateTime.now());
            emp.setUpdateTime(LocalDateTime.now());
            emp.setDeptId(1);
    
            empMapper.insert(emp);
        }
    
  • 控制台

    在这里插入图片描述

  • emp表

在这里插入图片描述

主键返回
  • 描述:在数据添加成功之后,需要获取插入数据库数据的主键。如:添加套餐数据时,还需要维护套餐菜品关系表数据。

在这里插入图片描述

//在上面的代码基础上,添加下面的注解就可以了。
@Option(keyProperty = 'id',useGeneratedKeys = true)
//会自动将生成的主键值,赋值给emp对象的id属性

//获得并输出id值
System.out.println(emp.getId());

在这里插入图片描述

5.3.3 更新
  • SQL语句

    update emp set username = '',name = '',gender = '',image = '',
    job = '',entrydate = '',dept_id = '',update_time = '' where id = x;
    
  • 接口方法

   //更新员工
    @Update("update emp set username = #{username}, name = #{name}, gender = #{gender}, image = #{image}," +
            " job = #{job}, entrydate = #{entrydate}, dept_id = #{deptId},update_time = #{updateTime} where id = #{id}")
    public void update(Emp emp);


//更新员工
    @Test
    public void testUpdate(){
        //构造员工对象
        Emp emp = new Emp();
        emp.setId(18);
        emp.setUsername("Tom1");
        emp.setName("汤姆1");
        emp.setImage("1.jpg");
        emp.setGender((short)1);
        emp.setJob((short)1);
        emp.setEntrydate(LocalDate.of(2000,1,1));
        emp.setUpdateTime(LocalDateTime.now());
        emp.setDeptId(1);

        //执行更新员工操作
        empMapper.update(emp);
    }
5.3.4 查询
根据ID查询
  • SQL语句
select * from emp where id = 1;
  • 接口方法

    //根据ID查询员工
        @Select("select * from emp where id = #{id}")
        public Emp getById(Integer id);
    
    
    //根据ID查询员工
        @Test
        public void testGetById(){
            Emp emp = empMapper.getById(20);
            System.out.println(emp);
        }
    
数据封装
  • 实体类属性名 和 数据库表查询返回的字段名一致,mybatis会自动封装。否则不会(未封装的字段查询返回null)。

在这里插入图片描述

方案
//方案一:给字段起别名,让别名与实体类属性一致
    @Select("select id, username, password, name, gender, image, job, entrydate, " +
            "dept_id deptId, create_time createTime, update_time updateTime from emp where id = #{id}")
    public Emp getById(Integer id);


//方案二: 通过@Results, @Result注解手动映射封装
@Results({
            @Result(column = "dept_id", property = "deptId"),
    //将字段"dept_id"封装到"deptId"
            @Result(column = "create_time", property = "createTime"),
            @Result(column = "update_time", property = "updateTime")
    })
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);

//方案三:开启mybatis的驼峰命名自动映射开关(可以自动将"a_con"封装成"aCon"),在application.properties中修改配置,推荐用这种。
mybatis.configuration.map-underscore-to-camel-case=true
//然后就可以根据ID查询员工
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);

在这里插入图片描述

条件查询

在这里插入图片描述

  • SQL语句

    select * from emp where name like '%张%' and gender = 1 and entrydate between '2010-01-01' and '2020-01-01' order by update_time desc;
    
  • 接口方法

    //由于查询出的结果可能不止一条,所以这里用List集合封装。另外,“#{}”是不能出现在引号之间的,因为编译mysql语句时,“#{}”会被"?"问号代替,结果就变成了'%?%',而问号占位符不能出现在引号之间。所以这里改成"${}"。
    
    @Select("select * from emp where name like '%${name}%' and gender = #{gender} and " +
                "entrydate between #{begin} and #{end} order by update_time desc ")
        public List<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
    
    //缺点:性能低、不安全、存在SQL注入问题
    
    //解决方案:使用concat()
        @Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +
                "entrydate between #{begin} and #{end} order by update_time desc ")
        public List<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
    

在这里插入图片描述

参数名说明
在早期springboot或者单独使用mybatis时,形参名需要添加注解@Param(),因为早期没有某个编译插件,编译之后别名会被替换掉,无法保存下来,那么对字段的封装就要求很高了。而使用@Param()可以解决这个问题。

在这里插入图片描述

5.3.5 XML映射文件
  • 规范

    • XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放在相同包下(同包同名)
    • XML映射文件的namespace属性为Mapper接口全限定名(类名)一致
    • XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致
  • 第一条规范

    • 先在resource目录下创建一个含多级目录且跟Mapper包名相同的包(创建含多级目录的包,域名之间不应该用点分隔,而应该用斜杠)

    在这里插入图片描述

    • 然后在创建的包中创建XML文件,直接在包中按照:文件->新建->文件->EmpMapper.xml创建即可。

在这里插入图片描述

  • 第二条规范

    • 在XML配置文件中都得有约束,我们先将约束代码复制粘贴到XML文件中(搜索mybatis中文网,在入门栏找到“探究已映射的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>
    
</mapper>
  • 然后将mapper的namespace属性跟接口名(带包名)一致。

    <?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.itheima.mapper.EmpMapper">
       
    </mapper>
    
  • 第三条规范

    • 将sql语句写在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.itheima.mapper.EmpMapper">
          <!--接口方法名就叫做list-->
          <!-- resultType:单条记录所封装的类型 ,我们这里把字段封装到了一个Emp类上。这里就是保持返回类型一致-->
          <select id = "list" resultType = "com.itheima.pojo.Emp">		
          select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and entrydate between #{begin} and #{end} order by update_time desc 
          </select>
      </mapper>
      
      //然后执行这个方法
      public List<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
      

      使用注解可以让代码看上去更简洁,但对于复杂的语句。Java注解不仅力不从心,还会让本就复杂的SQL语句变得混乱不堪。因此对于复杂的操作,最好用XML来映射语句。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值