MyBatis学习笔记

JDBC

  1. SQL 夹杂在java代码中,耦合度高
  2. 不易维护,频繁修改
  3. 代码冗长,开发效率高

MyBatis

  1. 轻量级,性能出色
  2. SQL 和 Java 编码分开,Java 代码专注业务 ,SQL语句专注数据
MyBatis 配置文件

配置连接数据库环境
引入映射文件

ORM(Object Relationship Mapping) 对象映射关系

  1. 类 对应 表
  2. 属性 对应 字段
  3. 对象 对应 记录、行

一张表通常对应一个mapper及一个mapper接口
mapper映射文件 namespace需要和mapper接口全类名保持一致。
mapper映射文件 SQL语句的id要和mapper接口中的方法名一致。

sql注入问题

某个网站的登录验证SQL查询代码为:

strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

恶意填入:

userName = “1’ OR ‘1’='1”;

passWord = “1’ OR ‘1’='1”;

那么最终SQL语句变成了:

strSQL = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

因为WHERE条件恒为真,这就相当于执行:

strSQL = "SELECT * FROM users;"

因此可以达到无账号密码亦可登录网站。

PreprareStatement

在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。

即SQL语句在程序运行前已经进行了预编译,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or ‘1=1’、数据库也会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令。

补充1:在页面输入的时候可以加入校验,不可输入sql关键字,不可输入空格,也可以防止SQL注入。

补充2:PreparedStatement比 Statement 更快

使用 PreparedStatement 最重要的一点好处是它拥有更佳的性能优势,SQL语句会预编译在数据库系统中。执行计划同样会被缓存起来,它允许数据库做参数化查询。使用预处理语句比普通的查询更快,因为它做的工作更少(数据库对SQL语句的分析,编译,优化已经在第一次查询前完成了)。为了减少数据库的负载,生产环境中德JDBC代码你应该总是使用PreparedStatement 。值得注意的一点是:为了获得性能上的优势,应该使用参数化sql查询而不是字符串追加的方式。

MyBatis

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

${} 字符拼接 本质
#{} 占位符 本质 (参数赋值)

MyBatis 获取各种参数
  1. 单个参数
 <!--    User getUserByUserName(String uname);-->

<!--   #{} 传输单个字符 括号里可以是任意 字符(建议传本含义)-->
<!--    ${} 注意单引号-->
    <select id="getUserByUserName" resultType="User">
        <!-- select * from t_user where uname = #{uname}-->
        select * from t_user where uname = '${uname}'
     </select>
  1. 多个参数
<!--    ser checkLogin(String uname,String pwd);-->
<!--    多个参数的时候,MyBatis 会先把 参数放在map集合中 -->
<!--  以 arg0, arg1, param1, param2 为key,参数值为value, Available parameters are [arg0, arg1, param1, param2]-->

    <select id="checkLogin" resultType="User">
       <!-- select * from t_user where uname = #{param1} and pwd = #{param2} -->
        <!--  select * from t_user where uname = #{arg0} and pwd = #{arg1}-->

        select * from t_user where uname = '${arg0}' and pwd = '${param2}'
    </select>

  1. 参数手动放入map集合,直接参数传map集合
<!--    User checkLoginByMap(Map<String,Object> mp);-->
<!-- 这里key 可以自定义-->
    <select id="checkLoginByMap" resultType="User">
        select * from t_user where uname = #{uname} and pwd = #{pwd}
    </select>
  1. 参数是实体类类型(常用)
<!--    int insertUser(User user);-->
<!--    以属性的方式访问属性值-->
    <insert id="insertUser">
        insert into t_user values(null,#{uname},#{pwd},#{email},#{type})
    </insert>
  1. @param 命名参数
<!--    User checkLoginByParam("uname") String uname,@Param("pwd") String pwd);-->
<!--    等价第二种和第三种结合 省略自动创建map ,可以用自定义key 和 param1 、 param2 ...-->
    <select id="checkLoginByParam" resultType="User">
       <!-- select * from t_user where uname = #{uname} and pwd = #{pwd}-->
        select * from t_user where uname = #{param1} and pwd = #{param2}
    </select>
查询返回map集合

适用没有实体类映射的查询,以字段为key,字段对应数据为value;Map<String,Object>

<!--    Map<String,Object> getUserByIdToMap(@Param("uid")int uid);-->
<!--    查询一条数据-->
    <select id="getUserByIdToMap" resultType="map">
        select * from t_user where uid = #{uid}
    </select>

<!--    @MapKey("uid")-->
<!--    Map<String,Object> getAllUsersToMap(@Param("uid")int uid);-->
<!--    查询多条数据-->
<!--加了注解后,会以某个字段作为key ,该条所有数据拼接后作为value,类似json数组-->
    <select id="getAllUsersToMap" resultType="map">

        select * from t_user
    </select>
MyBatis 一级缓存
SqlSession 的默认开启缓存

同一个SqlSession ,会将第一个查询数据进行缓存,再次查询相同数据就会从缓存中取,不从数据库取。

使一级缓存失效的四种情况

  1. 不同的SqlSession对应不同一级缓存
  2. 同一个SqlSession但查询条件不同
  3. 同一个SqlSession两次查询中执行了任意增删改操作
  4. 同一个SqlSession两次查询中手动清空了缓存
MyBatis 二级缓存
映射文件Cache标签开启 核心配置文件全局开启cacheEnable
  1. 通过SqlSessionFactory创建的SqlSession都可以用这个缓存
  2. 二级缓存必须在SqlSession关闭或提交之后有效
  3. 查询的数据所转换的实体类型必须实现序列化接口
  4. 两次查询中执行了任意增删改操作也会让二级缓存失效

缓存只适用于查询操作

缓存顺序
  1. 先查二级缓存,再一级缓存,最后数据库
  2. SqlSession关闭后,一级缓存会转到二级缓存
MyBatis 逆向工程

根据数据库表直接自动创建pojo和mapper接口

MyBatis 分页
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
isFirstPage/isLastPage:是否为第一页/最后一页
hasPreviousPage/hasNextPage:是否存在上一页/下一页
navigatePages:导航分页的页码数
navigatepageNums:导航分页的页码,[1,2,3,4,5]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值