1. MyBatis

MyBatis 是基于 JAVA 的持久层框架,它内部封装了 JDBC

通过 xml 或者 注解 方式使将要的执行各种 statement 配置起来 , 并通过 java对象和statement中SQL的动态参数进行映射生成最终执行的SQL语句

执行完SQL语句 并将结果映射为java对象返回 使用ORM 思想解决问题

2. ORM

Object Relational Mapping 对象关系映射 持久化数据和实体对象的映射模式

3. 使用

  • 导入 mybatis.jar 和mysql.jar

  • 在src下创建映射配置文件 名字无所谓

  1. -
  2. src下创建核心配置文件
  3. -
  4. ```xml
  5. <?xml version="1.0" encoding="UTF-8"?>
  6. <!DOCTYPE configuration
  7. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  8. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  9. <configuration>
  10. <!-- 默认配置-->
  11. <environments default="ie">
  12. <!-- 配置名-->
  13. <environment id="ie">
  14. <transactionManager type="JDBC"></transactionManager>
  15. <dataSource type="POOLED">
  16. <!-- 驱动-->
  17. <property name="driver" value="com.mysql.jdbc.Driver"/>
  18. <property name="url" value="jdbc:mysql://127.0.0.1:3306/mysql"/>
  19. <property name="username" value="root"/>
  20. <property name="password" value="123456"/>
  21. </dataSource>
  22. </environment>
  23. </environments>
  24. <!-- 映射类-->
  25. <mappers>
  26. <!-- 映射类名称-->
  27. <mapper resource="StudentMapper.xml"/>
  28. </mappers>
  29. </configuration>
  • 加核心配置文件

      1. InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
  • 获取sqlsession 工厂对象

      1. SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
  • 执行映射配置文件的sql语句

      1. List<Object> objects = sqlSession.selectList("StudentMapper.any");
  • 释放资源

      1. sqlSession.close();
      2. is.close();

4. Resources 加载资源工具类

  • Resources.getResourceAsStream(String fileName) 通过类加载器返回指定资源的字节输入流 与获取类加载 加载指定资源字节输入流一样

5. SqlSessionFactoryBuilder 工厂对象功能类

  • new SqlSessionFactoryBuilder().build(is); 通过指定资源字节输入流获取SqlSessionFactory工厂对象

6. SqlSessionFactory 对象

  • openSession() 获取sqlsession 构建者对象 并开启手动提交事务
  • openSession(boolean auotoCommit) 获取sqlsession 构建者对象 true为自动提交事务

7. SqlSession

构建者对象接口 用于执行 SQL 管理事务 接口代理

  • selectList(String Statement , object parameter) 执行查询语句 并返回list集合
  • selectList(String Statement , object parameter) 执行查询语句 返回一个结果对象
  • inser(String Statement , object parameter) 执行新增语句,返回影响行数
  • update(String Statement , object parameter) 执行修改语句,返回影响行数
  • delete(String Statement , object parameter) 执行删除语句,返回影响行数
  • commit() 提交事务
  • rollback() 回滚事务
  • getMapper(Class<T> cls) 获取指定接口的代理实现类对象
  • close() 释放资源

8. 映射配置文件

  • mapper 核心根标签

    • namespace属性 名称空间
  • select 查询标签

    • id属性 唯一标识
    • resultType属性 指定结果映射对象类型 类路径 增删改可以不指定类因为返回的是一个影响行数
    • parameterType属性 指定参数映射对象类型 指定执行时传递的parameter类型
    • SQL语句获取参数 #{属性名}
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="StudentMapper">
  6. <select id="any" resultType="com.xxx..xx" parameterType="java.lang.long">
  7. select * from mysql where id = #{id}
  8. </select>
  9. <insert id="insert" parameterType="笔记.jdbc.src.Student">
  10. insert into studen value (#{id},#{name},#{age})
  11. -- 从Student 中传递 id name age属性
  12. </insert>
  13. </mapper>

9. 核心配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <!-- configuration根标签-->
  6. <configuration>
  7. <!-- environments配置数据库环境 default属性指定使用哪一个-->
  8. <environments default="ie">
  9. <!-- environment配置数据库环境 id属性唯一标识-->
  10. <environment id="ie">
  11. <!-- transactionManager事务管理 type属性 采用jdbc默认的事务管理-->
  12. <transactionManager type="JDBC"></transactionManager>
  13. <!-- dataSource数据源信息 type属性 连接池 -->
  14. <dataSource type="POOLED">
  15. <!-- property连接数据库的配置信息-->
  16. <property name="driver" value="com.mysql.jdbc.Driver"/>
  17. <property name="url" value="jdbc:mysql://127.0.0.1:3306/mysql"/>
  18. <property name="username" value="root"/>
  19. <property name="password" value="123456"/>
  20. </dataSource>
  21. </environment>
  22. </environments>
  23. <!-- mappers引入映射配置文件-->
  24. <mappers>
  25. <!-- mapper 引入指定的映射配置 resource属性 指定映射配置文件的名名称-->
  26. <mapper resource="StudentMapper.xml"/>
  27. </mappers>
  28. </configuration>

10. 数据库连接配置引入

  • <properties> 引入数据库连接配置文件标签

    • resource属性 数据库连接配置文件路径
  • 获取连接参数

    • ${键名}
  1. driver=com.mysql.jdbc.Driver
  2. url=jdbc:mysql://127.0.0.1:3306/mysql
  3. username=root
  4. password=123456
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE configuration
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  5. <!-- configuration根标签-->
  6. <configuration>
  7. <!-- environments配置数据库环境 default属性指定使用哪一个-->
  8. <properties resource="笔记/mybatis/src/config.properties">
  9. <environments default="ie">
  10. <!-- environment配置数据库环境 id属性唯一标识-->
  11. <environment id="ie">
  12. <!-- transactionManager事务管理 type属性 采用jdbc默认的事务管理-->
  13. <transactionManager type="JDBC"></transactionManager>
  14. <!-- dataSource数据源信息 type属性 连接池 -->
  15. <dataSource type="POOLED">
  16. <!-- property连接数据库的配置信息-->
  17. <property name="driver" value="${driver}"/>
  18. <property name="url" value="${url}"/>
  19. <property name="username" value="${username}"/>
  20. <property name="password" value="${password}"/>
  21. </dataSource>
  22. </environment>
  23. </environments>
  24. <!-- mappers引入映射配置文件-->
  25. <mappers>
  26. <!-- mapper 引入指定的映射配置 resource属性 指定映射配置文件的名名称-->
  27. <mapper resource="StudentMapper.xml"/>
  28. </mappers>
  29. </configuration>

11. 起别名

在映射配置中 我们resultType属性需要提供 类的全路径 可以在核心配置文件中起别名来简写

  • <typeAliaser> 为全类名起别名的父标签
  • <typeAlias> 为全类名起步名的子标签

    • 属性:

      • type 指定全类名
      • alias 指定别名
  • <package> 为指定包下所有类起别的子标签 别名就是类名
  1. <typeAliases>
  2. <typeAlias type="笔记.jdbc.src.Student" alias="student"></typeAlias>
  3. </typeAliases>

01. MyBatis - 图1

12. LOG4J

在核心配置文件添加

  1. <settings>
  2. <setting name="logImpl" value="log4j"/>
  3. </settings>

并配置好log4j.properties 配置

13. 分层思想

控制层(controller) ====> 业务层(service) ====> 持久层(dao)

持久层 对接数据库

业务层 处理业务逻辑 此处只是暂时直接调用dao层的方法

控制层 使用 test类

14. 接口代理

通过接口代理 我们只需要写dao层的接口 由MyBatis 框架根据接口的定义来创建接口的动态代理对象

  • 映射配置文件中的名称空间必须与dao层接口的全类名相同
  • 映射配置文件中的增删改查的id属性必须和dao层接口的方法名相同
  • 映射配置文件中的增删改查标签的parameterType属性必须和dao层接口方法的参数相同
  • 映射配置文件中的增删改查标签的resultType属性必须和dao层接口的返回值相同

getMapper(Class<T> cls) 获取指定接口的代理实现类对象

  1. mybatisdemo01 mapper = sqlSession.getMapper(mybatisdemo01.class);

14.1. 源码分析

通过getMapper()方法 获取到 org.apache.ibatis.binding.MapperProxy 代理对象 底层使用 JDK 的动态代理技术 帮我们实现代理实现类对象

执行方法时调用了 mapperMethod.execute()方法 通过switch语句 判断操作类型是增删改查操作

通过SqlSession 方法来执行

15. 动态SQL

可以根据SQL语句动态根据条件查询

  • <where> 条件标签 如果有动态条件 则使用该标签替代where关键字
  • <if> 条件判断标签 test属性 条件控制 如果成立则拼接SQL语句
  1. <select id="dongtaisql" resultType="studen">
  2. select * from stden
  3. <where>
  4. <if test="id != null">
  5. id = #{id}
  6. </if>
  7. <if test="age != null">
  8. and age = #{age}
  9. </if>
  10. </where>
  11. </select>
  • <foreach> 循环遍历标签 适用于多个参数或者的关系

    • collection属性 参数容器类型(list集合 array数组)
    • open属性 开始的sql语句
    • close属性 结束的sql语句
    • item属性 参数变量名
    • separator属性 分隔符
  1. <!-- select * forme studen id in(1,2,3)-->
  2. <select id="selectbyids" resultType="studen" parameterType="list">
  3. select * from studen
  4. <where>
  5. <foreach collection="list" open="id in(" close=")" separator="," item="id">
  6. #{id}
  7. </foreach>
  8. </where>
  9. </select>

16. SQL 片段抽取

将一些重复性的SQL语句进行抽取 达到复用的效果

  • <sql> 标签 抽取sql语句标签 id属性唯一标识
  • <include> 引入sql片段标签 refid属性需要引用片段的唯一标识
  1. <sql id="select">select * from studen</sql>
  2. <select id="qsq" resultType="student" parameterType="student">
  3. <include refid="select"></include> where id = #{id}
  4. </select>

17. 获取自增的ID 再插入数据

先执行LAST_INSERT_ID() 返回一个id并封装在对象 再执行inser语句

  1. <insert id="add" parameterType="com.itheima.pojo.CheckGroup">
  2. <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
  3. select LAST_INSERT_ID()
  4. </selectKey>
  5. insert into t_checkgroup(code, name, sex, helpCode, remark, attention)
  6. values (#{code}, #{name}, #{sex}, #{helpCode}, #{remark}, #{attention})
  7. </insert>

18. 分页插件

mybatis不带分页功能的 mysql中分页使用 limit 语句 不同的数据库实现的关键字也不同

PageHelper 第三方分页助手

  • 导入jar包 pagehelper.jar jsqlparser.jar

  • 在核心配置文件中集成分页助手

      1. <plugins>
      2. <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
      3. </plugins>
  • 在测试类中使用分页功能

      1. PageHelper.startPage(1,3);
      2. // PageHelper.startPage(第几页,每页显示多少个); 设置分页参数

18.1. Pageinfo 封装分页相关参数的功能类

  • getTotal() 获取总条数
  • getPages() 获取总页数
  • getPageNum() 获取当前页
  • getPageSize() 获取每页显示条数
  • getPrePage() 获取上一页
  • getNextPage() 获取下一页
  • islsFiresPage() 获取是否是第一页
  • islsLastPage() 获取是否是最后一页
  1. PageInfo<Student> info =new PageInfo<>(list);
  2. int total = info.getTotal();

19. 多表操作

19.1. 一对一

  1. <mapper namespace="1v1">
  2. <!--
  3. resultMap 配置字段和实体对象属性的映射关系
  4. id为唯一标识
  5. type为映射对象路径
  6. -->
  7. <resultMap id="oneToOne" type="card">
  8. <!--
  9. id为主键标签 column为表中列名 property为对象属性名称
  10. result为其他列标签
  11. -->
  12. <id column="cid" property="id"/>
  13. <result column="number" property="number" />
  14. <!--
  15. association: 配置被包含对象的映射关系 对象内的对象
  16. property: 被包含对象的变量名 对象内的对象变量名是什么
  17. javaType:被包含对象的数据类型
  18. -->
  19. <association property="prs" javaType="person">
  20. <id column="pid" property="id"></id>
  21. <result column="name" property="name"/>
  22. <result column="age" property="age"/>
  23. </association>
  24. </resultMap>
  25. <!--
  26. resultMap 为多表操作映射
  27. -->
  28. <select id="selectall" resultMap="oneToOne">
  29. select c.id cid,number,pid,name,age from card c,person p where c.pid=p.id;
  30. </select>
  31. </mapper>
  • <resultMap> 配置字段和实体对象属性的映射关系

    • id属性 唯一标识
    • type属性 实体对象类型
  • <id> 配置主键映射关系标签
  • <result> 配置非主键映射关系标签

    • column属性 表中字段名称
    • property属性 实体对象变量名称
  • <association> 配置被包含对象的映射关系标签

    • property属性 被包含对象的变量名
    • javaType属性 被包含对象的数据类型

19.2. 一对多

  1. <mapper>
  2. <resultMap id="onetomany" type="classes">
  3. <id column="cid" property="id"/>
  4. <result column="canem" property="name"/>
  5. <!--
  6. collection: 配置被包含的集合对象映射关系
  7. property属性 被包含集合对象的变量名
  8. ofType属性 被包含集合对象元素的数据类型
  9. -->
  10. <collection property="students" ofType="student">
  11. <id column="sid" property="id"/>
  12. <result column="sname" property="name"/>
  13. <result column="sage" property="age"/>
  14. </collection>
  15. </resultMap>
  16. <select id="selectall" resultMap="onetomany">
  17. select c.id cid,c.name cname,s.id sid,s.name sname,s.age sage from classes c,student s where c.id=s.id
  18. </select>
  19. </mapper>
  • <collection> 配置被包含的集合对象映射关系

    • property属性 被包含集合对象的变量名
    • ofType属性 被包含集合对象元素的数据类型

19.3. 多对多

  1. <mapper>
  2. <resultMap id="manytomany" type="sstdent">
  3. <id column="sid" property="id"/>
  4. <result column="sname" property="name"/>
  5. <result column="sage" property="age"/>
  6. <collection property="coures" ofType="corse">
  7. <id column="cid" property="id"/>
  8. <result column="cname" property="name"/>
  9. </collection>
  10. </resultMap>
  11. <select id="selectall" resultMap="manytomany">
  12. select sc.sid,s.name sname,s.age sage,sc.cid,c.name cname from stdent s,course c,stu,_cr sc where sc.sid=s.id and sc.cid=c.id
  13. </select>
  14. </mapper>

<collection> 配置被包含的集合对象映射关系

  • property属性 被包含集合对象的变量名
  • ofType属性 被包含集合对象元素的数据类型

20. 注解

  • @Select(“查询的SQL语句”) 指定参数还是#{key}
  • @Insert(“新增的SQL语句”) 如:@Insert(“inser into student value (#{id},#{age},#{name})”)
  • @Update(“修改的SQL语句”)
  • @Delete(“删除的SQL语句”)

通过注解形式的操作 不需要创建映射配置文件 映射配置内容 写在核心配置文件中

  1. <mappers>
  2. <!-- name为接口所在的包路径 可以指定类或者指定包下的所有类 -->
  3. <package name="com.xxx.xxx.stdentmapper"/>
  4. </mappers>

19. 多表操作

19.1. 一对一

  1. @Select("select * fome card")
  2. @Results({
  3. @Result(column = "id" ,property = "id"),
  4. @Result(column = "number" , property = "number"),
  5. @Result(
  6. property = "p", // 被包含对象的变量名
  7. javaType = Person.class, // 被包含对象的实现数据类型类
  8. column = "pid", // 根据上面select查询出来表中的哪个字段来查询第二个表
  9. /*
  10. one = @one() 一对一写法
  11. select属性 指定调用哪个接口的哪个方法
  12. */
  13. one = @One(select = "com.xxx.xxx接口.selectByid方法")
  14. )
  15. })
  16. List<Card> selectAll();
  17. //@one注解调用的接口方法
  18. @Select("select * from person where id=#{id}")
  19. Person selectByid(Integer id);
  • @Results 封装映射关系的父注解 Result[] vlue() 定义了Result数组

    • @Result 封装映射关系的子注解

      • column属性 查询出的表中字段名称
      • property属性 实体对象中的属性名称
      • javaType属性 被包含对象的数据类型
      • one 属性 一对一查询

        • @One一对一查询注解

          • select属性 指向要调用某个接口中的方法

19.2. 一对多

  1. //一对多
  2. @Select("select * fome classes")
  3. @Results({
  4. @Result(column = "id" ,property = "id"),
  5. @Result(column = "number" , property = "number"),
  6. @Result(
  7. property = "students", // 被包含对象的变量名
  8. javaType = List.class, // 被包含对象的实现数据类型类
  9. column = "id", // 根据上面select查询出来表中的哪个字段来查询第二个表
  10. /* many = @Many() 一对多写法
  11. select属性 指定调用哪个接口的哪个方法*/
  12. many= @Many(select = "com.xxx.xxx接口.xxx方法")
  13. )
  14. })
  15. List<Classes> selectAll();
  16. //@one注解调用的接口方法
  17. @Select("select * from student where cid=#{cid}")
  18. List<Student> selectByid(Integer cid);
  • many属性 一对多查询

    • @Many一对多查询注解

      • select属性 指向要调用某个接口中的方法

19.3. 多对多

  1. //多对多
  2. @Select("select distinct s.id,s.name fome studebt s,stu_cr sc where sc.sid = s.id")
  3. @Results({
  4. @Result(column = "id" ,property = "id"),
  5. @Result(column = "number" , property = "number"),
  6. @Result(
  7. property = "students", // 被包含对象的变量名
  8. javaType = List.class, // 被包含对象的实现数据类型类
  9. column = "id", // 根据上面select查询出来表中的哪个字段来查询第二个表
  10. /* many = @Many() 一对多写法
  11. select属性 指定调用哪个接口的哪个方法*/
  12. many= @Many(select = "com.xxx.xxx接口.xxx方法")
  13. )
  14. })
  15. List<Student> selectAll();
  16. //@one注解调用的接口方法
  17. @Select("select c.id,c.name from stu_cr sc,course c where sc.cid=c.id and sc.sid=#{id}")
  18. List<Course> selectByid(Integer id);
  • many属性 一对多查询

    • @Many一对多查询注解

      • select属性 指向要调用某个接口中的方法

21. SQL 构建

01. MyBatis - 图2

  1. public static void main(String[] args) {
  2. System.out.println(getSelectall());
  3. //SELECT *
  4. //FROM student
  5. }
  6. public static String getSelectall(){
  7. return new SQL(){
  8. {
  9. SELECT("*");
  10. FROM("student");
  11. }
  12. }.toString();
  13. }
  • @SelectProvider(type = SQL构造的类.class , mehod = “要执行类中方法”) 查询

  • @InsertProvider((type = SQL构造的类.class , mehod = “要执行类中方法”) 新增

    1. public static String getInsert(Student stu){
    2. return new SQL(){
    3. {
    4. INSERT_INTO("student");
    5. INTO_VALUES("#{id},#{age},#{name}");
    6. }
    7. }.toString();
    8. }