什么是Mybatis
mybatis是JAVA领域中的一款持久化框架。它的主要功能是让我们轻松的在JAVA对象和数据库之间建立联系。通过这种联系,开发者可以很方便的存储、检索和操作数据。以下是Mybatis和其他ORM框架相比的一些特点:
- Mybatis强调对SQL的可控性,在使用的时候,可以直接编写SQL语句,提供更精准的优化查询。还可充分利用数据库的特性,处理各种复杂的业务逻辑。在某些情况下,能够带来更好的性能。
- Mybatis不会自动将对象和数据库表进行完全的映射,这跟其他ORM框架的做法不同。在使用Mybatis时,需要手动编写映射配置,把JAVA对象的属性和数据表的列进行关联。虽说这种方式需要更多的操作,但也正是这种方式让映射过程更加可控,尤其适用于处理复杂的数据结构。
相对于其他ORM框架,MyBatis更加灵活。它允许开发者直接操控SQL语句,并手动控制对象与数据库表之间的映射关系。这使得MvBatis在需要精细控制数据库操作以及处理复杂映射关系场景中更加具有优势。而其他一些ORM框架则更适合简化开发流程,减少样板代码的编写。
Mybatis的优点和缺点
优点:
- Mybatis是使用SQL语句进行编程,非常灵活。可以将SQL写在XML中,这样可以避免和代码或数据库设计产生冲突,也便于集中管理。Mybatis还提供XML标签,用来编写动态SQL语句,而且可以重复利用。可根据不同情况灵活的生成SQL。
- 与使用JDBC相比,Mybatis能减少超过50%的代码,也省去了很多JDBC冗余的操作,不需要手动来回打开关闭数据库连接,减轻了开发负担。
- Mybatis能够很好的兼容各种数据库,因为它是基于JDBC连接数据库,只要是JDBC支持的数据库,Mybatis都能支持。这使得在不同的项目中,甚至不同类型的数据库之间切换变得非常方便。
- Mybatis能够轻松与Spring框架集成,给项目带来很大得便利。
- 对象个数据库之间得映射,Mybatis提供了映射标签()可以方便得将对象和数据库的字段关系映射起来。此外对象关系映射标签还支持对象关系组件的维护,这是一个很有用的功能。
缺点:
- mybatis虽然强大,但是编写SQL语句可能会相对繁琐,特别是当涉及多个字段或多个关联表时。这就要求开发人员在SQL编写方面有一定的功底。
- 由于SQL语句依赖于特定的数据库,如果想要更换数据库移植性会受到一定的影响,这意味着不能轻易更改数据库,可能需要进行一些适应性的修改。
Mybatis与JPA有哪些不同
- 编程模型的不同:Mybatis和JPA采用不同的方式来处理数据操作。Mybatis采用基于SQL的编程模型,意味着开发者需要自己编写SQL语句,并且将其映射到java方法。JPA采用基于对象的编程模型,用户只需定义实体类并使用注解将实体映射到数据表中,JPA会自动生成SQL语句】开发人员无需过关心底层SQL的细节。
- SQL控制:Mybatis可以编写和优化SQL语句,在需要特定优化或使用数据库特性时非常有用。而JPA则将大部分SQL细节隐藏,自动生成SQL语句,在某些情况下可能会影响性能或限制操作。
- 灵活性和控制:Mybatis提供了更多的灵活性,适用于需定制化SQL查询或调用存储过程的场景。JPA则提供了更高层次的抽象,用于简化常见的数据库操作。在某些高级或者是复杂的情况下会产生一些限制。
- 查询语言:Mybatis使用原生的SQL作为查询语言,要求开发人员对SQL有一定的了解。JPA则引入了JPQL作为查询语句,更加的面向对象,类似于SQL,但是操作的是实体对象。
- 缓存方面:Mybatis的缓存控制更加精细,可以更准确的控制缓存的行为。JPA虽然也支持缓存,但通常对缓存的控制较少,更多的由框架自身控制。
- 学习曲线:Mybatis对熟悉SQL的开发人员来说,上手较快。JPA的学习曲线比较平缓,因为隐藏了更多的细节,一些高级特性需要长时间来理解。
Mybatis的核心组件有哪些
- SqlSessionFactoryBuilder (构造器):使用Builder模式根据mybatis-config.xml配置或者代码来生成SqISessionFactory。
- SqlSessionFactory:SqlSessionFactory是一个会话工厂,主要的作用是用来创建SqlSession对象,这个对象是我们与数据库交互的主要途径。SqlSessionFactory还可以帮助配置数据库连接信息和事务管理等。该工厂一旦被创建就会加载一些必要配置和映射文件,为后续的数据库操作提供一个可靠的基础。
- SqlSession:代表一次数据库的会话,提供了一系列方法来执行Sql语句,提交或事务回滚,还可以获取Mapper接口实例。不过SqlSession的生命周期是短暂的,通常在数据库操作完成之后就需要关闭,以释放资源。
- Mapper:Mybatis的重要组件,由一个XML文件和一个jAVA接口组成,用于定义SQL语句的结果映射规则。Mapper接口方法和SQL映射语句之间存在一一对应的关系。
Mybatis的工作流程
- 加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。
- SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。
- SqlSession对象完成和数据库的交互:
- 用户程序调用mybatis接口层api(即Mapper接口中的方法)
- SqlSession通过调用api的Statement ID找到对应的MappedStatement对象
- 通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象
- JDBC执行sql。
- 借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。
Mybatis的一级缓存和二级缓存
一级缓存:
- 一级缓存是Mybatis默认开启并且不可关闭的,是针对SqlSession级别的缓存。生命周期与SqlSession的生命周期一致。
- 当执行查询时,首先会从一级缓存中检查是否存在相同查询语句的结果,如果有则直接返回结果,避免对数据库进行访问提高查询效率。
- 缓存键:一级缓存的键是由SQL语句、参数值和结果映射组成。这意味着相同的SQL语句和参数值会公用缓存。
- 缓存失效:当SqlSession关闭或提交后,以及执行了任何更新操作(插入、更新、删除)之后缓存会失效。
二级缓存:
- 缓存范围:二级缓存的作用域是Mapper级别是SqlSessionFactory级别的,即同一个Mapper对象中的查询结果可以被多个SqlSession共享。
- 缓存的配置:你可以在 Mapper 的 XML 文件或注解中配置二级缓存的开启与关闭,以及缓存的刷新策略、缓存大小等。
- 缓存对象的序列化:为了能在多个 SqlSession 间共享缓存数据,二级缓存中的对象需要支持序列化。你可以自定义实现
Serializable
接口的对象或使用 MyBatis 提供的缓存插件。 - 缓存的更新:当执行更新操作时,MyBatis 会清除相关的二级缓存,以保证缓存数据的一致性。
启用二级缓存:
-
application.properties中配置开启全局缓存
mybatis.configuration.cacheEnabled=true
-
Mapper 文件中,你可以添加 `` 元素来启用二级缓存
<!-- mapper/UserMapper.xml -->
<mapper namespace="com.example.demo.mapper.UserMapper"><cache /><!-- 查询语句 -->
</mapper>
-
或者是使用注解的方式
@CacheNamespace public interface UserMapper {// 查询方法 }
Mybatis如何处理延迟加载
延迟加载是一种优化方法,目标是为了在查询数据库的时候,尽量不读取多余的数据,从而提高我们应用的表现和节约资源。在Mybatis里,延迟加载的技巧主要是用于在处理对象关系映射的时候,也就是ORM。
延迟加载的好处:
- 提高性能:在对象关系较为复杂或者是数据多的情况下,延迟加载可以减少一次性加载大量数据,让查询更快,应答更快。
- 节省资源:可以按需加载,不一开始加载所有关联数据,节约了内存和网络资源。
- 避免不必要的查询:如果有些关联数据在当前情景下用不上,用延迟加载就能避免没不要的数据查询,不累积数据库的负担。
但要注意,虽然延迟加载能提升性能,可别用得过了,免得碰上懒加载的N+1问题,就是要查很多次才能拿到关联数据,结果性能就拖垮了。所以用延迟加载的时候,得根据实际情况合理配置和使用。
Mybatis中的动态Sql是什么
动态SQL是Mybatis中的一个强大的特性,允许根据不同的条件在运行时动态构建不同的SQL语句。
假设用户需要根据不同的条件搜索商品,例如商品名,价格或者是分类,可以使用动态SQL构建一个灵活的查询语句,在用户提供相关条件的时候包含这些条件。
在Mybatis中可以使用、、、等标签构建动态SQL。
动态SQL使得构建更加的灵活,适应不同情况的查询变得方便。减少代码的重复,提高代码的可维护性和可读性。
Mybatis中的XML映射有哪些标签
除了常见的select、insert、update、delete标签,Mybatis的XML映射文件中还存在一些其他的标签用于复杂的操作和配置。下面是一些常见的标签:
- resultMap:用于定义查询结果与JAVA对象之间的映射关系,可以在多个查询中重复使用。
- association和collection:用于在resultMap中定义关联关系,用于处理一对一一对多的关系。
- sql:用于定义可重用的SQL片段,然后在其他地方引用,用于减少重复编写的SQL语句
- include:用于在SQL语句中引入外部定义的SQL片段,提高可维护性。
- if、choose、when、otherwise:用于在SQL中进行条件判断和逻辑控制,用于动态的条件构建。
- trim、where、set:用于在SQL语句中添加固定的SQL片段,如where和set关键字,用于动态的条件构建。
- foreach:用于在SQL语句中进行集合迭代,适用于生成IN语句等。
- bind:用于SQL语句中申明并且绑定一个变量,适合生成IN语句。
- cache:用于配置二级缓存。
- selectKey:用于在插入操作后获取生成的主键值。
Mybatis中模糊查询语句怎么写
-
字符串拼接方式
<select id = "searchUser" resultMap = "userResultMap">SELECT * FROM users WHERE username LIKE CONCAT('%',#{keyword},'%') </select>
-
动态SQL方式
<select id = "searchUser" resultMap = "userResultMap">SELECT * FROM users <where><if>AND username LIKE CONCAT('%',#{keyword},'%')</if></where></select>
#{}和${}的区别是什么?
- #{}(预编译或者是占位符)
- #{}是用于预编译的参数标记,当使用#{}时候,Mybatis会将参数值放入一个预编译的PreparedStatement中并确保参数值被正确的转义和引用,从而防止SQL注入攻击。
- ${}(字符串替换)
- 是用于字符串替换的参数标记。当使用 {}是用于字符串替换的参数标记。当使用 是用于字符串替换的参数标记。当使用{}时,Mybatis会直接将参数值嵌入SQL语句中,不会进行预编译或转义。这存在潜在的安全问题,有SQL注入的风险。
总结区别:
#{}用于预编译,提供参数安全性,适合大多数情况
${}用于字符串替换,潜在安全风险较高,仅在特定情况下使用,确保参数值安全。在实际使用中,推荐优先使用 #{}来处理参数,以确保数据库操作的安全性和可靠性。只有在确保参数值不会引发安全问题的情况下,才应该考虑使用 ${}。
Mybatis中二级缓存的缺点
- 数据不一致性:如果某个地方改了数据,但是缓存里的数据没有及时更新,其他地方拿到的数据就可能是过时的,这样可能会引发错误。
- 占用内存空间:使用二级缓存需要一些内存空间来存储数据。如果数据很多,可能会占用比较多的内存,这有可能会影响引用程序的运行速度。
- 维护成本:在使用二级缓存的时候,需要考虑数据什么时候更新、什么时候删除等等,这会让代码变得复杂,需要更多的开发和测试工作。
Mybatis中二级缓存的适用场景
- 如果我们的应用程序更多是读取数据,写操作相对较少,那么二级缓存就能够很有效地减少数据库访问的次数,提升性能。
- 还有,如果我们的数据变化不是很频繁,即使缓存里的数据不是最新的,也不会对应用产生太大的影响,这时候也可以考虑用二级缓存。
- 另外,如果某些查询的耗时比较长,但是查询结果又不怎么变化,用了二级缓存就可以加快这些查询的速度。
Mybatis中二级缓存的不适用场景
- 如果应用程序对数据的实时性要求很高,二级缓存可能就不太适合,因为缓存里的数据可能会有点滞后。
- 如果我们应用里有很多频繁的写操作,可能会导致缓存一直失效,这样就得不偿失了,可能还会增加数据库的压力。
- 如果涉及到复杂的数据模型或者数据之间的关联关系,使用缓存的维护和数据一致性可能会变得更加复杂。