-
创建 SqlSessionFactory 对象。
-
通过 SqlSessionFactory 获取 SqlSession 对象。
-
通过 SqlSession 获得 Mapper 代理对象。
-
通过 Mapper 代理对象,执行数据库操作。
-
执行成功,则使用 SqlSession 提交事务。
-
执行失败,则使用 SqlSession 回滚事务。
-
最终,关闭会话。
-
使用Sql 拼接,有语句大小限制
INSERT INTO [表名]([列名],[列名]) VALUES ([列值],[列值])), ([列值],[列值])), ([列值],[列值]));
-
使用Mybatis 的批量插入方式
private static SqlSessionFactory sqlSessionFactory; @Test public void testBatch() { // 创建要插入的用户的名字的数组 List<String> names = new ArrayList<>(); names.add("张三"); names.add("李四"); names.add("李二"); names.add("王五"); // 获得执行器类型为 Batch 的 SqlSession 对象,并且 autoCommit = false ,禁止事务自动提交 try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH, false)) { // 获得 Mapper 对象 UserMapper mapper = session.getMapper(UserMapper.class); // 循环插入 for (String name : names) { mapper.insertUser(name); } // 提交批量操作 session.commit(); } }
-
使用循环一条条插入
不同的 XML Mapper 文件,如果配置了 "namespace" ,那么 id 可以重复;如果没有配置 "namespace" ,那么 id 不能重复。毕竟"namespace" 不是必须的,只是最佳实践而已。
原因就是,namespace + id 是作为 Map<String, MappedStatement> 的 key 使用的。如果没有 "namespace",就剩下 id ,那么 id 重复会导致数据互相覆盖。如果有了 "namespace",自然 id 就可以重复,"namespace"不同,namespace + id 自然也就不同。
Mybatis 将所有 XML 配置信息都封装到 All-In-One 重量级对象Configuration内部。
在 XML Mapper 文件中:
-
<parameterMap>标签,会被解析为 ParameterMap 对象,其每个子元素会被解析为 ParameterMapping 对象。 -
<resultMap>标签,会被解析为 ResultMap 对象,其每个子元素会被解析为 ResultMapping 对象。 -
每一个
<select>、<insert>、<update>、<delete>标签,均会被解析为一个 MappedStatement 对象,标签内的 SQL 会被解析为一个 BoundSql 对象。
Mapper 接口,对应的关系如下:
- 接口的全限名,就是映射文件中的
"namespace"的值。 - 接口的方法名,就是映射文件中 MappedStatement 的
"id"值。 - 接口方法内的参数,就是传递给 SQL 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名 + 方法名拼接字符串作为 key 值,可唯一定位一个对应的 MappedStatement 。举例:com.mybatis3.mappers.StudentDao.findStudentById ,可以唯一找到 "namespace" 为 com.mybatis3.mappers.StudentDao 下面 "id" 为 findStudentById 的 MappedStatement 。
总结来说,在 Mybatis 中,每一个 <select />、<insert />、<update />、<delete /> 标签,都会被解析为一个 MappedStatement 对象。
另外,Mapper 接口的实现类,通过 MyBatis 使用 JDK Proxy 自动生成其代理对象 Proxy ,而代理对象 Proxy 会拦截接口方法,从而“调用”对应的 MappedStatement 方法,最终执行 SQL ,返回执行结果。整体流程如下图:
-
其中,SqlSession 在调用 Executor 之前,会获得对应的 MappedStatement 方法。例如:
DefaultSqlSession#select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler)方法,代码如下:// DefaultSqlSession.java @Override public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) { try { // 获得 MappedStatement 对象 MappedStatement ms = configuration.getMappedStatement(statement); // 执行查询 executor.query(ms, wrapCollection(parameter), rowBounds, handler); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
Mapper 接口里的方法,是不能重载的,因为是全限名 + 方法名的保存和寻找策略
