MyBatis基础
文章目录
一、MyBatis
1、是什么
MyBatis 是一款优秀的持久层框架,一个半 ORM(对象关系映射)框架,它支持定 制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置 参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接 口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
2、干什么
替代 JDBC 的——加载驱动 获取连接 Statement/PreparedStatement 书写 sql 执⾏
要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。
MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。通过 xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。(从执行 sql 到返回 result 的过程)。
二、MyBatis 优点和缺点
2.1优点
- 简单易学。mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar加配置几个sql映射文件,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现;
- 灵活。mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多;
- 解除sql与程序代码的耦合。通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性;
- 提供映射标签,支持对象与数据库的orm字段关系映射;
- 提供对象关系映射标签,支持对象关系组建维护;
- 提供xml标签,支持编写动态sql。
2.2、缺点
- SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL 语句的功底有一定要求。
- SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
- mybatis 为半自动化,需要自己书写sql语句,需要自己定义映射
- JDBC方式可以用打断点的方式调试,但是Mybatis不能,需要通过Log4j日志信息帮助调试,然后在配置文件中修改
三、MyBatis 核心类
当 Mybatis 与一些依赖注入框架(如 Spring 或者 Guice)搭配使用时,
SqlSession将被依赖注入框架创建并注入,所以你不需要使用 SqlSessionFactoryBuilder 或者SqlSessionFactory,可以直接阅读 SqlSession 这一节。
请参考 Mybatis-Spring 或者Mybatis-Guice 手册以了解更多信息。
3.1、SqlSession
使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通过这个接口来执行命令,获取映射器实例和管理事务。
SqlSessions 是由 SqlSessionFactory 实例创建的。SqlSessionFactory 对象包含创建 SqlSession 实例的各种方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的,它可以从 XML、注解或 Java 配置代码来创建 SqlSessionFactory。
它包含了所有执行语句、提交或回滚事务以及获取映射器实例的方法。
/** * Copyright 2009-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.session; import java.io.Closeable; import java.sql.Connection; import java.util.List; import java.util.Map; import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.executor.BatchResult; /** * The primary Java interface for working with MyBatis. * Through this interface you can execute commands, get mappers and manage transactions. * * @author Clinton Begin */ public interface SqlSession extends Closeable { /** * Retrieve a single row mapped from the statement key. * @param <T> the returned object type * @param statement * the statement * @return Mapped object */ <T> T selectOne(String statement); /** * Retrieve a single row mapped from the statement key and parameter. * @param <T> the returned object type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @return Mapped object */ <T> T selectOne(String statement, Object parameter); /** * Retrieve a list of mapped objects from the statement key. * @param <E> the returned list element type * @param statement Unique identifier matching the statement to use. * @return List of mapped object */ <E> List<E> selectList(String statement); /** * Retrieve a list of mapped objects from the statement key and parameter. * @param <E> the returned list element type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @return List of mapped object */ <E> List<E> selectList(String statement, Object parameter); /** * Retrieve a list of mapped objects from the statement key and parameter, * within the specified row bounds. * @param <E> the returned list element type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param rowBounds Bounds to limit object retrieval * @return List of mapped object */ <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); /** * The selectMap is a special case in that it is designed to convert a list * of results into a Map based on one of the properties in the resulting * objects. * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id") * @param <K> the returned Map keys type * @param <V> the returned Map values type * @param statement Unique identifier matching the statement to use. * @param mapKey The property to use as key for each value in the list. * @return Map containing key pair data. */ <K, V> Map<K, V> selectMap(String statement, String mapKey); /** * The selectMap is a special case in that it is designed to convert a list * of results into a Map based on one of the properties in the resulting * objects. * @param <K> the returned Map keys type * @param <V> the returned Map values type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param mapKey The property to use as key for each value in the list. * @return Map containing key pair data. */ <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey); /** * The selectMap is a special case in that it is designed to convert a list * of results into a Map based on one of the properties in the resulting * objects. * @param <K> the returned Map keys type * @param <V> the returned Map values type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param mapKey The property to use as key for each value in the list. * @param rowBounds Bounds to limit object retrieval * @return Map containing key pair data. */ <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); /** * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. * @param <T> the returned cursor element type. * @param statement Unique identifier matching the statement to use. * @return Cursor of mapped objects */ <T> Cursor<T> selectCursor(String statement); /** * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. * @param <T> the returned cursor element type. * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @return Cursor of mapped objects */ <T> Cursor<T> selectCursor(String statement, Object parameter); /** * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. * @param <T> the returned cursor element type. * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param rowBounds Bounds to limit object retrieval * @return Cursor of mapped objects */ <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds); /** * Retrieve a single row mapped from the statement key and parameter * using a {@code ResultHandler}. * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param handler ResultHandler that will handle each retrieved row */ void select(String statement, Object parameter, ResultHandler handler); /** * Retrieve a single row mapped from the statement * using a {@code ResultHandler}. * @param statement Unique identifier matching the statement to use. * @param handler ResultHandler that will handle each retrieved row */ void select(String statement, ResultHandler handler); /** * Retrieve a single row mapped from the statement key and parameter using a {@code ResultHandler} and * {@code RowBounds}. * * @param statement * Unique identifier matching the statement to use. * @param parameter * the parameter * @param rowBounds * RowBound instance to limit the query results * @param handler * ResultHandler that will handle each retrieved row */ void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); /** * Execute an insert statement. * @param statement Unique identifier matching the statement to execute. * @return int The number of rows affected by the insert. */ int insert(String statement); /** * Execute an insert statement with the given parameter object. Any generated * autoincrement values or selectKey entries will modify the given parameter * object properties. Only the number of rows affected will be returned. * @param statement Unique identifier matching the statement to execute. * @param parameter A parameter object to pass to the statement. * @return int The number of rows affected by the insert. */ int insert(String statement, Object parameter); /** * Execute an update statement. The number of rows affected will be returned. * @param statement Unique identifier matching the statement to execute. * @return int The number of rows affected by the update. */ int update(String statement); /** * Execute an update statement. The number of rows affected will be returned. * @param statement Unique identifier matching the statement to execute. * @param parameter A parameter object to pass to the statement. * @return int The number of rows affected by the update. */ int update(String statement, Object parameter); /** * Execute a delete statement. The number of rows affected will be returned. * @param statement Unique identifier matching the statement to execute. * @return int The number of rows affected by the delete. */ int delete(String statement); /** * Execute a delete statement. The number of rows affected will be returned. * @param statement Unique identifier matching the statement to execute. * @param parameter A parameter object to pass to the statement. * @return int The number of rows affected by the delete. */ int delete(String statement, Object parameter); /** * Flushes batch statements and commits database connection. * Note that database connection will not be committed if no updates/deletes/inserts were called. * To force the commit call {@link SqlSession#commit(boolean)} */ void commit(); /** * Flushes batch statements and commits database connection. * @param force forces connection commit */ void commit(boolean force); /** * Discards pending batch statements and rolls database connection back. * Note that database connection will not be rolled back if no updates/deletes/inserts were called. * To force the rollback call {@link SqlSession#rollback(boolean)} */ void rollback(); /** * Discards pending batch statements and rolls database connection back. * Note that database connection will not be rolled back if no updates/deletes/inserts were called. * @param force forces connection rollback */ void rollback(boolean force); /** * Flushes batch statements. * @return BatchResult list of updated records * @since 3.0.6 */ List<BatchResult> flushStatements(); /** * Closes the session. */ @Override void close(); /** * Clears local session cache. */ void clearCache(); /** * Retrieves current configuration. * @return Configuration */ Configuration getConfiguration(); /** * Retrieves a mapper. * @param <T> the mapper type * @param type Mapper interface class * @return a mapper bound to this SqlSession */ <T> T getMapper(Class<T> type); /** * Retrieves inner database connection. * @return Connection */ Connection getConnection(); }
3.2、SqlSessionFactory
创建SqlSession的
SqlSessionFactory 有六个方法创建 SqlSession 实例。
package org.apache.ibatis.session; import java.sql.Connection; /** * Creates an {@link SqlSession} out of a connection or a DataSource * * @author Clinton Begin */ public interface SqlSessionFactory { SqlSession openSession(); SqlSession openSession(boolean autoCommit); SqlSession openSession(Connection connection); SqlSession openSession(TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType); SqlSession openSession(ExecutorType execType, boolean autoCommit); SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }
3.3、SqlSessionFacotryBuilder
创建 sqlSessionFacotry 对象的。
有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。
SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) SqlSessionFactory build(InputStream inputStream, String env, Properties props) SqlSessionFactory build(Configuration config)
/** * Copyright 2009-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ibatis.session; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.Properties; import org.apache.ibatis.builder.xml.XMLConfigBuilder; import org.apache.ibatis.exceptions.ExceptionFactory; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory; /** * Builds {@link SqlSession} instances. * * @author Clinton Begin */ public class SqlSessionFactoryBuilder { public SqlSessionFactory build(Reader reader) { return build(reader, null, null); } public SqlSessionFactory build(Reader reader, String environment) { return build(reader, environment, null); } public SqlSessionFactory build(Reader reader, Properties properties) { return build(reader, null, properties); } public SqlSessionFactory build(Reader reader, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { reader.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(InputStream inputStream) { return build(inputStream, null, null); } public SqlSessionFactory build(InputStream inputStream, String environment) { return build(inputStream, environment, null); } public SqlSessionFactory build(InputStream inputStream, Properties properties) { return build(inputStream, null, properties); } public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } } } public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } }
Mybatis的执行流程
- mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。 - 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
- 由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
- mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
- MappedStatement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
- MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
- MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
四、Mybatis缓存
- 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
- 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
- 对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新
五、Mybatis延迟加载原理
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,多对一,collection指的就是一对多,多对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
参考文章
个人笔记,不同意见,望有交流
直接可以点击跳转连接
作者
面试题
#{}和${}的区别是什么?
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”.
$将传入的数据直接显示生成在sql中。
如:order by u s e r i d user_id userid,如果传入的值是111,那么解析成sql时的值为order by 111, 如果传入的值是id,则解析成的sql为order by id.- #方式能够很大程度防止sql注入。
‘$’ 方式无法防止Sql注入
。Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;Mybatis在处理 时 , 就 是 把 {}时,就是把 时,就是把{}替换成变量的值。select * from emp where empno = 7360 or 1=1 – ${}select * from emp where empno = ‘7369’ – #{}没有特殊需求情况下,都要使用#{}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用