前言
首先感谢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的全名称一致的原因)