mybatis源码阅读-helloword

前言

首先感谢https://my.oschina.net/zudajun/blog/665956(jd上也出书了貌似)  这位作者。让自己能系统的看完和理解第一个框架的源码(其实我反复看了4遍以上,一遍实际操作 一边打断点一边看)。我现在发现学习一个框架首先会简单的应用,然后才是阅读源码进阶,不然直接抱着源码肯,会很晕。所以首先记录mybatis的各种用法开始。

写博客的主要原因是方便后面自己快速查阅。

使用SqlSession完成CRUD

1.引入mybatis相关依赖

 <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.0</version>
        </dependency>
    <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
         <!-- 数据源 c3p0 -->
      <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5-pre8</version>
        </dependency>
   </dependencies>

2.创建测试相关的表

CREATE TABLE classes
(
  id INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '班级id',
  `name` VARCHAR(50) NOT NULL COMMENT '班级名称'
)

3.创建对应的实体类

public class Classes implements Serializable{
    private int id;
    private String name;

    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    

    public void setName(String name) {
        this.name = name;
    }

    
}

4.创建mybatis配置文件

mybatis.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" />
            <!--UNPOOLED  非连接池    POOLED mybatis提供的POOLED连接池    JNDI mybtais提供的JNDIfacotory获取数据源
               根据配置找到对应的工厂 创建对应的数据源  可以直接配置工厂 需要实现UnpooledDataSourceFactory
            -->
            <dataSource type="com.liqiang.core.C3P0DataSourceFactory">
                <property name="driverClass" value="com.mysql.jdbc.Driver" />
                <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/DTest?characterEncoding=UTF-8" />
                <property name="user" value="root" />
                <property name="password" value="root" />
            </dataSource>
        </environment>
    </environments>
    <!-- mapping 支持是三种方式 类全明称  包扫描   mapperXml路径 -->
    <mappers>
        <mapper resource="ClassesMapper.xml"></mapper>
       <!-- <mapper class=""></mapper>
         <package name="com.liqiang.mapper"/>-->
    </mappers>

</configuration>

上面dataSource Type 因为mybatis不支持c3p0所以通过他提供的结构自定义连接池创建工厂

public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
     public C3P0DataSourceFactory () {
           this . dataSource = new ComboPooledDataSource () ;
        }
}
UnpooledDataSourceFactory 继承这个  然后构造函数 初始化 初始化c3p0的数据源对象

5.定义一个在resources下增加 ClassesMapper.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="classes">
    <select id="selectAll" resultType="com.liqiang.entity.Classes">
    select * from classes
    </select>
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.liqiang.entity.Classes">
        insert INTO classes(name) VALUES (#{name});
    </insert>
    <update id="update"  parameterType="com.liqiang.entity.Classes">
        UPDATE classes set name=#{name} where id=#{id};
    </update>
    <delete id="delete" parameterType="int">
        delete from classes where id=#{id};
    </delete>
</mapper>
parameterType为传入参数类型
useGeneratedKeys 为是否使用JDB3KeyGenerated(可以理解成自增情况下插入会回填id) keyProperty为回填自增id的属性名字
6.测试
    public static void main(String[] args) throws FileNotFoundException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder
                .build(ClassLoader.getSystemResourceAsStream("mybatis.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //新增
        Classes classes=new Classes();
        classes.setName("一年级");
        sqlSession.insert("classes.insert",classes);
        sqlSession.commit();
        //查询
        List<Classes> list=sqlSession.selectList("classes.selectAll");
        list.forEach(c->{
            System.out.println(c.getName());
        });
        //修改
        classes.setName("二年级");
        sqlSession.update("classes.update",classes);
        sqlSession.commit();
        list=sqlSession.selectList("classes.selectAll");
        list.forEach(c->{
            System.out.println(c.getName());
        });

        //删除
        sqlSession.delete("classes.delete",list.get(0).getId());
        sqlSession.commit();

暂时理解:

               1.解析mybatis.xml 扫描mappers下面 把对应的标签通过 namespace+id当key把各个map形式存储起来

               2.通过sqlSession的CRUD方法 传入key 执行对应的sql

使用代理完成CRUD

1.创建一个mapper包,并将ClassesMapper.xml移动到里面,并创建一个mapper接口,方法名字和返回类型 参数类型要对应ClassesMapper.xml

public interface ClassesMapper {
     public List<Classes> select();
     public void  update(Classes classes);
     public void  insert(Classes classes);
     public void delete(int id);

}

2.将ClassesMapper.xml的namespace改成对应Mapper接口的全名称(必须)

<mapper namespace="com.liqiang.mapper.ClassesMapper">
   ...
</mapper>

3.修改mybatis下的xml扫描 变为包扫描

<mappers>
        <package name="com.liqiang.mapper"/>
</mappers>

理解:

         1.mybatis会扫描这个包下面所有类型为interface的class

         2.然后遍历这些class通过classname+.xml 找到对应的mapper.xml(这就是为什么这种方式mapper接口和mapper.xml名字要一致的原因)

4.测试

public static void main(String[] args) throws FileNotFoundException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder
                .build(ClassLoader.getSystemResourceAsStream("mybatis.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        ClassesMapper classesMapper=sqlSession.getMapper(ClassesMapper.class);

        //新增
        Classes classes=new Classes();
        classes.setName("一年级");
        classesMapper.insert(classes);
        sqlSession.commit();
        //查询
        List<Classes> list=sqlSession.selectList("classes.selectAll");
        list.forEach(c->{
            System.out.println(c.getName());
        });
        //修改
        classes.setName("二年级");
        classesMapper.update(classes);
        sqlSession.commit();
        list=classesMapper.select();
        list.forEach(c->{
            System.out.println(c.getName());
        });

        //删除
        classesMapper.delete(list.get(0).getId());
        sqlSession.commit();
}

理解:

         1.sqlSession.getMapper会获得对应接口的代理类,调用对应的方法 底层会获得代理类实现接口的全名称packagename+接口名字+当前方法名字做key找到对应的mapper标签(这就是基于代理namespace一定要跟对应mapper的全名称一致的原因)

猜你喜欢

转载自www.cnblogs.com/LQBlog/p/9276981.html