网站 服务报价,wordpress链接排序,典型的网络营销案例,小说网站怎么做流量文章目录 Mybatis 框架SQL执行过程数据库操作映射方式SQL的执行过程- SQL解析- SQL参数映射- SQL预编译- SQL执行- 结果映射- 事务处理- 缓存处理- 日志记录与监控 扩展#与$的区别- $ 符号- # 符号总结示例 Mybatis SQL分类- 动态 SQL- 静态 SQL静态SQL和动态SQL选择${}、#{}与… 文章目录 Mybatis 框架SQL执行过程数据库操作映射方式SQL的执行过程- SQL解析- SQL参数映射- SQL预编译- SQL执行- 结果映射- 事务处理- 缓存处理- 日志记录与监控  扩展#与$的区别- $ 符号- # 符号总结示例 Mybatis SQL分类- 动态 SQL- 静态 SQL静态SQL和动态SQL选择${}、#{}与SQL是否静态SQL、动态SQL无直接关系   Mybatis 框架 SQL执行过程 数据库操作映射方式 
MyBatis支持两种方式进行数据库操作映射 
映射文件通过XML文件来定义SQL语句和映射关系注解方式通过在Java代码中使用注解来定义SQL语句和映射关系 
这两种方式都可以实现数据库操作的映射具体使用哪种方式取决于个人的喜好和项目需求。本文都以映射文件的方式进行分析。 
SQL的执行过程 SQL解析 MyBatis 会将SQL 语句解析为内部的数据结构。这一过程中MyBatis 会根据 SQL 中的参数类型、数量等信息生成一个 MappedStatement 对象表示当前的 SQL 语句及其相关的执行元数据。  参数绑定 在 SQL 解析完成后MyBatis 会在 SQL 参数映射阶段将 SQL 语句中的参数与 Java 对象进行映射并将参数值处理成符合数据库预编译要求的形式。这样在 SQL 预编译和执行阶段就可以正确地传递参数并执行 SQL 语句。  SQL预编译 MyBatis 利用 JDBC 的 PreparedStatement 接口进行 SQL 语句的预编译。预编译过程会将 SQL 中的占位符?替换为实际参数并将其转化为数据库可以优化执行的形式从而提高 SQL 执行效率。  执SQL行 完成预编译后MyBatis 会通过 JDBC API 将 SQL 语句提交给数据库执行并获取查询结果或执行结果。数据库执行完成后结果会返回给 MyBatis 进行进一步处理。  结果映射 MyBatis 会将数据库返回的结果集转换为相应的 Java 对象。这一过程包括类型转换、字段匹配等通常通过 TypeHandler 来完成。TypeHandler 负责将数据库中的列值与 Java 对象的属性进行映射。  事务处理 如果启用了手动事务管理MyBatis 会在 SQL 执行完成后根据配置的事务管理策略提交或回滚事务确保数据一致性和事务的完整性。  缓存处理 若启用了缓存MyBatis 会将查询结果存储到缓存中以便下次执行相同的 SQL 语句时能够直接从缓存中获取结果从而减少数据库的访问频率提高性能。MyBatis 支持一级缓存SqlSession 范围内和二级缓存跨 SqlSession 的共享缓存。  日志记录与监控 MyBatis 会通过集成日志框架如 Log4j、SLF4J记录 SQL 执行的详细日志。这些日志信息可以帮助开发人员分析 SQL 执行的性能发现潜在的问题优化查询效率。  
最后将查询结果返回给调用方自此完成整个 SQL 执行过程。 
下面详细介绍每一个过程 
- SQL解析 
当 MyBatis 执行一个查询时首先会对传入的 SQL 语句进行解析解析 SQL 语句的结构和参数信息为后续的参数绑定和执行做准备。 
解析过程会进行语法分析和语义分析以确保SQL语句的正确性分析 SQL 语句中的参数占位符并提取出需要传入的参数类型和数量。将 SQL 语句转化为 MyBatis 内部可识别的数据结构 
MyBatis 使用 XML 或注解中的 SQL 语句结合映射文件中的 MappedStatement 对象来表示 SQL 信息。MappedStatement 是 MyBatis 核心的配置对象包含了 SQL 的元数据、类型处理器、缓存策略等。 
解析过程涉及到标签的解析、参数的解析和动态SQL的处理 
标签解析 首先会解析映射文件的根节点select、insert、update、delete等然后逐个解析其中的标签。解析标签时MyBatis会根据标签的不同类型如查询、插入、更新、删除执行相应的解析逻辑。 动态SQL处理 MyBatis支持动态SQL即根据不同的条件在运行时动态生成SQL语句。\动态SQL使用一系列XML标签如if、choose、when、otherwise等进行条件判断和 SQL片段的组装。在解析映射文件时MyBatis会对动态SQL片段进行解析并根据条件判断生成最终的SQL语句。动态SQL的处理涉及到条件判断、循环、字符串拼接等操作以根据运行时的条件生成最终的SQL语句。  
参考 
select idfindUserById resultTypeUserSELECT * FROM users WHERE id  #{id}
/select 
在上述例子中findUserById 是一个 MappedStatement 对象#{id} 是一个占位符。 
- SQL参数映射 
MyBatis 在 SQL 参数映射阶段会将用户提供的参数绑定到 SQL 语句中的占位符。根据映射文件或注解中的 SQL 语句MyBatis 会分析哪些占位符需要绑定哪些参数。这样在 SQL 预编译和执行阶段就可以正确地传递参数并执行 SQL 语句。 
在 MappedStatement 中有一个 BoundSql 对象它包含了实际的 SQL 语句以及绑定的参数。BoundSql 会根据 SQL 的占位符如 ? 或 #{}将传入的参数与 SQL 语句进行绑定。 - MyBatis 首先会解析 SQL 语句识别其中的占位符#{}或者字符串替换${}形式的参数。 - 对于 ${} 形式的参数MyBatis 会直接将参数值替换到 SQL 语句中需要谨防SQL注入问题。 
参考 
MapString, Object params  new HashMap();
params.put(id, 1);
userMapper.findUserById(params);params 中的 id 将会绑定到 SQL 语句中的 #{id} 占位符。 
- SQL预编译 
MyBatis使用JDBC的PreparedStatement接口创建预编译的SQL语句预编译的SQL语句中使用占位符如?代替参数。通过 SQL 预编译提升执行效率并确保参数的安全性。 
预编译有助于提高执行效率因为 SQL 语句只需要解析一次数据库会优化执行计划避免每次都解析 SQL。PreparedStatement 允许 MyBatis 在数据库执行时才将参数值填充到预编译的 SQL 中从而提高执行效率并避免 SQL 注入攻击。 
参考 
PreparedStatement ps  connection.prepareStatement(SELECT * FROM users WHERE id  ?);
ps.setInt(1, 1);将第一个参数id设置为 1 
- SQL执行 
MyBatis 会通过 JDBC API 将编译后的 SQL 语句提交到数据库执行。执行过程会获取执行结果例如查询结果或更新、删除操作的影响行数。 
执行时MyBatis 会通过 Statement 或 PreparedStatement 接口执行 SQL。查询操作会返回一个 ResultSet更新、删除等操作会返回受影响的行数。如果执行的是查询操作MyBatis 会进一步处理返回的 ResultSet并将其转换为 Java 对象。 
参考 
ResultSet rs  ps.executeQuery();- 结果映射 
执行 SQL 后MyBatis 会将数据库返回的 ResultSet 映射为相应的 Java 对象。这个映射过程会根据 SQL 查询的字段与 Java 对象的属性进行转换。 
MyBatis 使用 ResultMap 来定义如何将查询结果映射到 Java 对象。ResultMap 可以指定每个字段与对象属性之间的映射关系。例如使用 TypeHandler 进行类型转换比如将数据库中的 VARCHAR 类型转换为 String 类型。对于复杂的结果映射MyBatis 允许嵌套的映射以及集合类型的处理。 
参考 
resultMap iduserResultMap typeUserresult propertyid columnid/result propertyname columnname/
/resultMap- 事务处理 
MyBatis 支持手动和自动事务管理。默认情况下MyBatis 使用 JDBC 提供的事务控制。在执行数据库操作后MyBatis 会根据配置决定是否提交或回滚事务。 
如果使用自动提交autocommittrue事务会在每个操作后立即提交。如果使用手动事务管理开发者需要显式地调用 commit() 或 rollback() 来提交或回滚事务。事务处理保证了操作的一致性即在一个事务中的多个操作要么全部成功要么全部失败。 
参考 
sqlSession.commit();  // 提交事务
sqlSession.rollback();  // 回滚事务- 缓存处理 
MyBatis 提供了一级缓存和二级缓存机制来提高查询效率。一级缓存是 SqlSession 级别的缓存而二级缓存是跨 SqlSession 的共享缓存。 
一级缓存在同一个 SqlSession 中查询的结果会被缓存。只要没有关闭 SqlSession再次查询相同的 SQL 会直接从缓存中获取结果而不是重新查询数据库。二级缓存不同 SqlSession 之间可以共享缓存。二级缓存的使用需要在 MyBatis 配置文件中显式启用并且每个映射器可以配置自己的缓存策略。缓存机制有助于提高性能尤其是在查询频繁但数据变化较少的场景中。 
- 日志记录与监控 
MyBatis 可以集成各种日志框架如 Log4j、SLF4J 等来记录 SQL 执行过程中的信息。开发人员可以通过日志输出 SQL 执行的详细信息包括查询语句、执行时间等。 
MyBatis 的日志记录对于开发人员调试 SQL 和优化性能非常有帮助。日志框架可以配置为不同的日志级别例如 DEBUG、INFO、ERROR 等方便查看不同详细度的信息。 
参考 
settingssetting namelogImpl valueSLF4J/
/settings扩展 
#与$的区别 
- $ 符号 
$符号占位符是简单的字符串替换不进行预编译和参数类型处理也不会进行转义。$符号占位符直接将参数的值替换到SQL语句中可以用于动态拼接SQL语句的部分内容。$符号占位符存在SQL注入的风险因为参数值直接替换到SQL语句中可能导致恶意注入攻击。最终SQL的动态参数值一定不会有引号包裹 
- # 符号 
#符号占位符是预编译的占位符会对参数进行类型处理和安全处理。#符号占位符将参数值作为预编译参数传递给数据库可以防止SQL注入攻击。#符号占位符可以用于动态生成SQL语句的条件部分例如WHERE子句、ORDER BY子句等。最终SQL的动态参数值可能会有引号包裹不是一定都会有引号包裹 字符串类型会自动将其包裹在单引号中。数字类型不会自动加单引号。日期类型会格式化日期并加上单引号。  
总结示例 
示例 username的值为haha(String) 
1. 使用$占位符 
SELECT id, username, email FROM users WHERE username  ${username}
# 最终实际执行的sql
SELECT id, username, email FROM users WHERE username  haha2. 使用#占位符 
SELECT id, username, email FROM users WHERE username  #{username}
# 最终实际执行的sql
SELECT id, username, email FROM users WHERE username  hahaMybatis SQL分类 
根据 SQL 查询的特性来区分的可以将SQL分为动态 SQL 和静态 SQL。 
- 动态 SQL 
使用动态SQL可以根据不同的条件生成不同的SQL语句从而实现灵活的查询和更新操作。动态SQL可以使用if、choose、when、otherwise等标签来实现条件判断和循环操作同时还可以使用foreach标签来实现对集合类型参数的遍历操作。这样可以避免在代码中使用大量的字符串拼接提高代码的可读性和维护性。 
动态 SQL 的特点 
可以根据不同的条件生成不同的 SQL 查询。可以在查询语句中动态地添加、删除或修改部分 SQL 逻辑。提供了更大的灵活性和动态性可以根据运行时的条件来动态生成查询语句。 
常见的动态 SQL 的示例 
使用条件语句如 IF、CASE来动态选择不同的查询分支。使用循环语句如 FOR、WHILE来生成重复或动态数量的查询条件。使用动态连接条件来构建动态查询条件。使用动态排序来指定不同的排序方式。 
- 静态 SQL 
静态 SQL 的特点 
查询语句的结构和逻辑是固定的在执行查询时不会发生变化。SQL 查询不受外部参数的影响参数值在查询中直接拼接。 
常见的静态 SQL 的示例 
简单的选择查询语句不需要根据条件改变查询逻辑。固定的更新语句不受外部参数影响。预定义的查询模板参数值直接拼接在查询语句中。创建表格、索引等静态结构定义。 
静态SQL和动态SQL选择 
由于静态sql是在应用启动的时候就解析而动态sql是在执行该sql相关操作的时候才根据传入的参数进行解析的所以静态sql效率会比动态sql好。 
${}、#{}与SQL是否静态SQL、动态SQL无直接关系 
${} 和 #{} 只是占位符用来插入参数它们本身并不决定 SQL 是静态还是动态。动态 SQL 是通过 条件判断如 、来决定 SQL 的结构是否变化。即使 SQL 中使用了 ${} 或 #{}如果没有动态条件它仍然是静态 SQL。 
示例1 使用了${} 、#{}不是动态SQL 
select idgetUserById resultTypeUserSELECT id, username, emailFROM usersWHERE id  #{id}
/select这里的 #{id} 用来传递参数但 SQL 本身 是固定的没有根据任何条件变化。这个查询并不是动态 SQL因为它没有任何动态部分比如没有使用 标签。 
示例2 使用 ${} 来动态拼接表名不是动态SQL 
select idgetUsersByTableName resultTypeUserSELECT id, username, emailFROM ${tableName}WHERE id  #{id}
/select这里的 ${tableName} 是动态的会根据传入的 tableName 参数拼接成不同的表名。但 SQL 结构本身依然是 固定的只是表名不同。 
示例3 使用了${} 、#{}是动态SQL 
select idselectUsers resultTypeUserSELECT id, username, emailFROM userswhereif testusername ! nullAND username  #{username}/ifif testemail ! nullAND email  #{email}/if/where
/select使用了 标签来动态地添加 SQL 条件因此整个 SQL 是动态的。如果 username 和 email 参数存在SQL 语句就会加入对应的 AND 条件如果不存在这些条件会被忽略。这个查询才是真正的动态 SQL因为它的结构根据输入的参数变化。但 #{} 只是用来传递参数它和是否动态没有直接关系