深入理解MyBatis(一)基础及工作原理

GitHub:https://github.com/JDawnF

一、MyBatis编程步骤

  1. 创建 SqlSessionFactory 对象。

  2. 通过 SqlSessionFactory 获取 SqlSession 对象。

  3. 通过 SqlSession 获得 Mapper 代理对象。

  4. 通过 Mapper 代理对象,执行数据库操作。

  5. 执行成功,则使用 SqlSession 提交事务。

  6. 执行失败,则使用 SqlSession 回滚事务。

  7. 最终,关闭会话。

当 Java 代码通过 JDBC 的 PreparedStatement 向 DB 发送一条 SQL 语句时,DBMS 会首先编译 SQL 语句,然后将编译好的 SQL 放入到 DBMS 的数据库缓存池中再执行。当 DBMS 再次接收到对该数据库操作的 SQL 时,先从 DB 缓存池中查找该语句是否被编译过,若被编译过,则直接执行,否则先编译后将编译结果放入 DB 缓存池,再执行。

二、#{}${} 的区别

${} 是 Properties 文件中的变量占位符,它可以用于 XML 标签属性值和 SQL 内部,属于字符串替换。例如将 ${driver}会被静态替换为 com.mysql.jdbc.Driver

 <dataSource type="UNPOOLED">
     <property name="driver" value="${driver}"/>
     <property name="url" value="${url}"/>
     <property name="username" value="${username}"/>
 </dataSource>

${} 也可以对传递进来的参数原样拼接在 SQL 中(有sql注入的风险)。字符串拼接是将参数值以硬编码的方式直接拼接到了 SQL 语句中。字符串拼接就会引发两个问题:SQL 注入问题与没有使用预编译所导致的执行效率低下问题。

代码如下:

 <select id="getSubject3" parameterType="Integer" resultType="Subject">
     SELECT * FROM subject
     WHERE id = ${id}
 </select>

resultType 属性并非指查询结果集最后的类型,而是每查出 DB 中的一条记录,将该记录封装成为的对象的类型。resultMap 是对 resultType的增强。

#{}是 SQL 的参数占位符,Mybatis 会将 SQL 中的 #{} 替换为 ? 号,在 SQL 执行前会使用 PreparedStatement 的参数设置方法,按序给 SQL 的 ? 号占位符设置参数值,比如 ps.setInt(0, parameterValue) 。 所以,#{}是预编译处理,可以有效防止 SQL 注入,提高系统安全性。

另外,#{}${} 的取值方式非常方便。例如:#{item.name} 的取值方式,为使用反射从参数对象中,获取 item 对象的 name 属性值,相当于 param.getItem().getName()

#{ }:对指定参数类型属性值的引用。其底层是通过反射机制,调用实体类相关属性的 get 方法来获取值的。因为底层使用的是反射,所以这里使用的是类的属性名,而非表的字段名。

三、实体类中的属性名与表中的字段名绑定

第一种, 通过在查询的 SQL 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。代码如下:

 <select id="selectOrder" parameterType="Integer" resultType="Order"> 
     SELECT order_id AS id, order_no AS orderno, order_price AS price 
     FROM orders 
     WHERE order_id = #{id}
 </select>
  • 1、数据库的关键字,统一使用大写,例如:SELECTASFROMWHERE

  • 2、每 5 个查询字段换一行,保持整齐。

  • 3、, 的后面,和 = 的前后,需要有空格,更加清晰。

  • 4、SELECTFROMWHERE 等,单独一行,高端大气。

第二种,是第一种的特殊情况。大多数场景下,数据库字段名和实体类中的属性名差,主要是前者为下划线风格,后者为驼峰风格。在这种情况下,可以直接配置如下,实现自动的下划线转驼峰的功能。

 <setting name="logImpl" value="LOG4J"/>
     <setting name="mapUnderscoreToCamelCase" value="true" />
 </settings>

第三种,通过 <resultMap> 来映射字段名和实体类属性名的一一对应的关系。代码如下:

 <resultMap type="me.gacl.domain.Order" id=”OrderResultMap”> 
     <!–- 用 id 属性来映射主键字段 -–> 
     <id property="id" column="order_id"> 
     <!–- 用 result 属性来映射非主键字段,property 为实体类属性名,column 为数据表中的属性 -–> 
     <result property="orderNo" column ="order_no" /> 
     <result property="price" column="order_price" /> 
 </resultMap>
 <select id="getOrder" parameterType="Integer" resultMap="OrderResultMap">
     SELECT  order_no
     FROM orders 
     WHERE order_id = #{id}
 </select>

四、Mybatis工作原理如下:

Dao 实现类:

posted @ 2019-05-31 01:25  白晨冬阳  阅读(99)  评论(0编辑  收藏  举报