重新学习Mybatis(一)

前言:工作这么长时间,从刚毕业的SSM就开始接触mybatis,再到后来的springboot,然后到现在的springcloud。mybatis一直做为和数据库交互的框架。最近发现,虽然mybatis一直在用,但是好像也仅仅是用,原理什么的好像也不太清楚,决定从头开始,了解mybatis到底做了什么。

传统JDBC同数据库的交互方式:简单的代码,这个时代还是JSP+Servlet+Mysql+JDBC的时代

// 这里是一个User对象
User user = this.getUser();
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriveManager.getConnection(url,username,password);
// 用?防止SQL注入
String sql = "insert into user (id,name,age) values (?,?,?)";
PreparedStatement prepare = conn.prepareStatement(sql);
// 为上面的三个参数赋值
prepare.setString(1,user.getId);
prepare.setString(2,user.getName);
prepare.setInt(3,user.getAge);
// 第一种情况:执行SQL,获得受影响的行数
int rows =  prepare.executeUpdate();

// 第二种情况:执行查询SQL,获取结果集
string querySql = "select * from user";
Result result = prepaer.executeQuery();

while(res.next()){
  // 对结果集的操作
   res.getString(1);
   res.getString(2);
}
// 关闭
res.close();
prepare.close();
conn.close

1.加载驱动

2.获取数据库连接

3.书写SQL、并对SQL中的参数进行赋值

4.获取结果集

5.关闭连接

Spring出现、Mybatis出现,二者相结合。

其实Spring也好,Mybatis也好,官方介绍都是基本从XML文件开始给出的示例,即使到现在XML使用少了,但是整体的结构是不变的,这个后面会说到。个人建议,先从XML配置文件入门学习,在现如今springboot、springcloud横行的时代,虽然大家都能在框架里写东西,但是一旦配置出了问题,或者自己动手配置的时候基本只能照着已有的项目进行粘贴、复制。所有还是要至少了解一下各个框架的基本原理,死记硬背是永远不行的。

Mybatis基本配置如下:文件名字为mybatis-config.xml,这个配置文件结构很重要

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
   <environments default="development">
       <environment id="development">
           <transactionManager type="JDBC"></transactionManager>
           <dataSource type="POOLED">
               <property name="driver" value="com.mysql.jdbc.Driver"/>
               <property name="url" value="jdbc:mysql://localhost:3306/dhb?serverTimezone=UTC"/>
               <property name="username" value="root"/>
               <property name="password" value="12345"/>
           </dataSource>
       </environment>
   </environments>
    <mappers>
        <!--单个mapper文件的配置-->
        <mapper resource="mapper/UserMapper.xml"/>
        <!--整个dao包下面的配置-->
        <!--<package name="com.example.mybatis.demomybatis.dao"/>-->
    </mappers>
</configuration>

可以看出Mybatis的顶级为configuration元素,接下来是environment元素,里面配置了事务类型、数据源、在数据源里配置数据库驱动、url、username、password。接下来是一个一个的mapper文件,resource配置的是每个mapper.xml的路径,也可以批量配置。

UserMapper.java接口如下:

public interface UserMapper {

    void addUser(UserEntity entity);
}

UserMapper.xml文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.demomybatis.dao.UserMapper">
    <insert id="addUser" parameterType="com.example.mybatis.demomybatis.entity.UserEntity">
        INSERT INTO user (id, name, age) values (#{id},#{name},#{age})
    </insert>
</mapper>

这里先不使用spring和mybatis结合的方式进行,先把mybatis怎么运行的搞懂再和spring结合。

这里直接使用官方文档给出的示例,做一个简单的插入操作:

@SpringBootTest
public class MybatisTests {

    @Test
    public void testConfiguration() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        // 读取配置文件,将所有配置好的Mapper接口,在XMLConfigBuilder中parseConfiguration方法里的mapperElement子方法里加进去,
        // 最终的执行方法在XMLMapperBuilder.parse()里的bindMapperForNamespace()调用,
        // Configuration.addMapper()方法里通过MapperRegistry.addMapper()方法,
        // 放到一个Map里面去,
        // 该Map的Key是Mapper接口的完整路径(仅仅是接口路径而不是接口下面具体方法的路径,要注意,接口方法的具体路径会在下面动态代理那里拿到),
        // 该Map的value是构造一个新的MapperProxyFactory,
        // MapperProxyFactory以便于后面调用sqlSession.getMapper(Mapper接口.class)可以通过该MapperProxyFactory生成当前Mapper接口的动态代理类MapperProxy,
        // 具体可参考MapperRegistry.getMapper()方法即可,里面就是一个new了一个Mapper接口的动态代理对象 MapperProxy
        SqlSessionFactory factory = builder.build(inputStream);
        SqlSession sqlSession = factory.openSession();
        UserEntity entity = new UserEntity();
        entity.setAge(77);
        entity.setName("op7");
        entity.setId(7);
        // 第一种方式、获取对应的mapper,然后调用对应的方法即可,这里获取的UserMapper 的动态代理类MapperProxy对象
       // UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 执行的时候调用MapperProxy.invoke方法执行,里面最后会执行 mapperMethod.execute(sqlSession, args),
        // 然后MapperMethod.execute(),根据不同的SQLCommand(insert,update,delete,select)执行sqlSession.insert等不同的方法,
        // 接下来的执行就和第二种方式一毛一样了
       // mapper.addUser(entity);
        // 第二种方式、直接调用sqlsession的内置方法,两个参数,第一个参数是,mapper里的具体方法的完整路径,第二个参数是方法的入参
        sqlSession.insert("com.example.mybatis.demomybatis.dao.UserMapper.addUser",entity);
        sqlSession.commit();
        sqlSession.close();
    }
}

可以看出核心insert是有SqlSession对象完成的。SqlSession是有SqlSessionFactory.openSessoin()开启的,SqlSessionFactory又是由SqlSessionFactoryBuilder.build(读取的配置文件)生成的。

这里写了两种方式完成了insert操作,先以官方的方式、第二种方式分析。

sqlSession.insert("Mapper.方法","参数"),debug发现,接下来执行

参数就是我们第一步传的参数,第一个参数为Mapper里的方法的完整路径,第二个参数为该方法的参数,一个对象

首先会在全局configuration中拿到MapperStatement对象,这个至关重要,至于什么时候把MapperStatemnt放到configuration中的,会面会细说。包括MapperStatemnt中的sqlCommandType和statementType都会详细解释,本篇不做讨论。

接下来会执行DefaultSession里的update方法,调用executor.update,注意执行到这里,已经知道里SQL命令类型为insert,Statement为PrepareStatement类型,至于怎么获得的,以后会说,这里只说SQL的执行整体流程。

接下来执行BaseExecutor里的update方法,最终会由BaseExecutor的其中一个子类SimpleExecutor执行update方法

这里的关键两行代码是 stmt = prepareStatement()这个方法,和handler.update(),基本所有的最终的操作是在这两步完成的,debug进去看看到底干了什么

看到这个方法里的方法名字就知道了,获取连接和设置事务,再结合传统的JDBC,是不是清晰了一点

最后一步进入PrepareStatementHandler(是BaseStatementHandler的子类),这里的ps.execute()是不是特别熟悉。

到此为止整个SQL的前半部分就是这样的,返回的结果集后面研究。

接下来研究前半段SQL究竟怎么执行的,Myabtis是如何将我们写的SQL和参数揉到一起,并且请求数据库进行操作的?第二篇分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值