1、源码分析
1.1、输入流关闭
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
往下跟
public SqlSessionFactory build(InputStream inputStream){
return build(inputStream, null, null);
}
往下跟
build() 的方法包含了inputStream.close();——它将数据读入内存中,紧接着(finally)把流关闭了
所有说,调用**build()**方法已经把流关闭了。
1.2、SqlSession的创建
sqlSession = SqlSessionFactory.openSession();
往下跟SqlSessionFactory的实现类:DefaultSqlSessionFactory.class
如果调用的是openSession()的有参方法,可以设置autoCommit的值,;如果是无参的方法,则autoCommit默认是false
往下跟
environment:执行环境;
transactionFactory:事务工厂(比如事务管理器使用JDBC);
tx:获取到的事务对象;
executor:创建的执行器;
往下跟(return new DefualtSqlSession(configuration, executor, autoCommit);)
new的DefualtSqlSession,实际上是对成员变量赋初值(初始化工作):
其中,this.dirty = false;,这个变量很重要!!!
表示内存里的数据和数据库里的数据不一致时,它就是脏的,即this.dirty = true,当你准备写入或者修改数据库数据时。
1.3、增删改的执行
sqlSession.insert("insertStudent",student);
往下跟DefaultSqlSession.class
增删改,其本质上(底层代码)都是public int update(statement,Object parameter)
看!此时,dirty = true;但是为什么呢?
因为此时需要改数据了,所以将dirty赋值成true.
一执行update(statement,Object parameter);,即一改数据,那么同时数据库里的数据和此时的数据就不一致了,所以dirty = true。
1.4、SqlSession的提交commit()
sqlSession.commit();
往下跟,DefaultSqlSession.class
往下跟**isCommitOrRollbackRequired()**方法
private boolean isCommitOrRollbackRequired(boolean force){
return (!autoCommit && dirty) || force;
}
往下跟(DefaultSqlSession.class)BaseExecutor.class
commit()方法中包含了
if(required){
transaction.commit();
}
此时,事务就提交了!
事务提交完成后,dirty = false;
1.5、SqlSession的关闭
sqlSession.close();
如果前面发生了提交commit(),那么执行到此时,dirty = false
往下跟DefaultSqlSession.class中的close方法
往下跟**isCommitOrRollbackRequired()**方法(和3.4节重了)
private boolean isCommitOrRollbackRequired(boolean force){
return (!autoCommit && dirty) || force;
}
往下跟BaseExecutor.class中的close方法
事务不为空,即
if (transaction != null) {
transaction.close();
}
此时,事务关闭!
往下跟rollback方法
执行到此,transaction.rollback方法不执行,即事务没有回滚。
如果前面没有发生提交commit(),那么此时的dirty = true,那么
private boolean isCommitOrRollbackRequired(boolean force){
return (!autoCommit && dirty) || force;
}
此时,以上的方法会返回true;
相同的步骤,transaction.rollback方法会执行,即事务会回滚。
2、别名(两种方法,常用第二种)
2.1、主配置mybatis.xml文件的configuration标签目录下的typeAliases【其中alias:别名】
同时,在映射mapper.xml文件中,可以选择别名xxx;而不用选择com.huahua.beans.Student
当然,实际命名时,追求简介明了,一般选择简单的类名就ok!
2.2、主配置mybatis.xml文件的configuration标签目录下的package
将指定包中所有的类的简单类名当成对应类的别名[不含包名的类就是简单类名]
name属性:放实体所在的那个包
以下代码parameterType属性可以省略