一、Mybatis 概述

  • Mybatis 是一个使用java编写的持久层框架。它封装了 JDBC ,使开发者只需要关注 sql 语句,而无需关注注册驱动、创建连接、创建 Statement 等繁杂的过程
    • 采用了 ORM 思想 实现了结果集的封装
  • ORM(Object Relational Mapping)对象关系映射。简单地说,就是把数据库表和实体类及实体类的属性对应起来,让我们可以通过操作实体类来操作数据库表。

    二、Mybatis 实现CUD

    2.1 项目结构

    image.png

    2.2 导入jar包

    mybatis-3.5.4.jar
    mysql-connector-java-8.0.19.jar
    可选:lombok-1.12.2.jar

2.3 编写mybatis-config.xml配置文件

在src目录下创建mybatis-config.xml,其默认输入内容如下:

  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. <environments default="development">
  7. <environment id="development">
  8. <transactionManager type="JDBC"/>
  9. <dataSource type="POOLED">
  10. <property name="driver" value="${driver}"/>
  11. <property name="url" value="${url}"/>
  12. <property name="username" value="${username}"/>
  13. <property name="password" value="${password}"/>
  14. </dataSource>
  15. </environment>
  16. </environments>
  17. <mappers>
  18. <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  19. </mappers>
  20. </configuration>

根据自身需求修改后:

<?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">
<!-- dtd:约束文件,声明指定了一些标签,那么在引入了dtd文件的xml就只能够使用这些声明和的标签
    不能随意乱写
-->
<configuration>
    <!-- 引入分页插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
        </plugin>
    </plugins>

  <!-- 环境:可以配置多个环境
      default用于指定当前mybatis操作哪个数据库
   -->
  <environments default="development">
    <environment id="development">
      <!-- 事务管理器: 
          type="JDBC":使用JDBC的事务管理器管理事务
      -->
      <transactionManager type="JDBC"/>
      <!-- 配置数据源参数:
          type:POOLED        连接池:创建、管理数据库连接 connection对象
              举例:c3p0、dbcp、druid、hikari...
          POOLED 表示使用连接池 mybatis自带的
       -->
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/woniumall?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>
  <!-- 加载映射文件
      mybatis中将编写SQL语句的文件的叫做mapper文件
   -->
  <mappers>
      <!-- 加载mapper文件:读取mapper文件中的内容 sql,存放在内存中 
          快速注释:Ctrl+shift+/
          反注释:Ctrl+shift+\
      -->
    <!-- <mapper resource="org/mybatis/example/UserMapper.xml"/> -->
    <mapper resource="com/woniuxy/mapper/UserMapper.xml"/>
    <mapper resource="com/woniuxy/mapper/GoodsMapper.xml"/>
  </mappers>
</configuration>

2.4 创建User实体类

package com.woniuxy.entity;

import java.util.Date;

import lombok.Data;

@Data
public class User {
    private int id; // id
    private String account; // 账号
    private String password; // 密码
    private String email; // 邮箱
    private String avatar; // 头像
    private int score; // 积分
    private Date regtime; // 注册时间
    private String status; // 状态
}

由于导入了lombok.jar,可以使用@Data代替set,get,toString

2.5 编写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">

<!-- namespace:命名空间,作用与包名一样,区分相同id的SQL -->
<mapper namespace="abc">
  <!-- id为SQL的唯一标识,同一命名空间下不能有id相同的SQL 
      resultType:将查询出来的数据封装成什么类型的对象
  -->
  <select id="findAll" resultType="com.woniuxy.entity.User">
      select * from mall_user
  </select>

  <!-- 增 -->
  <insert id="add">
      insert into mall_user 
      values (default,#{account},#{password},#{email},
      #{avatar},#{score},#{regtime},#{status})
  </insert>

  <!-- 删
      如果参数是基本数据类型、包装类、string类型,获取参数时名字可以随意取
      但是建议与要操作的字段名字保持一致
  -->
  <delete id="delById">
      delete from mall_user where id = #{id};
  </delete>

  <!-- 改 -->
  <update id="changePwd">
      update mall_user set password = #{password} where account = #{account}
  </update>

</mapper>

2.6 创建CUD测试类,测试增、删、改功能

package com.woniuxy.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class CUDTest {

    public static void main(String[] args) throws IOException {

        // 自动到src下寻找配置文件
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 创建工厂
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
        // 创建Sqlsession实例
        // Sql会话
        SqlSession session = factory.openSession();

        // insert 新用户注册
//        User user = new User();
//        user.setAccount("sunqi");
//        user.setPassword("123456");
//        user.setEmail("55555@qq.com/");
//        user.setRegtime(new Date());
//        user.setStatus("0"); // 0表示新注册,未激活

        // 执行SQL
        // 添加user
//        session.insert("abc.add", user);

        // delete 根据id删除user
//        session.delete("abc.delById", 4);

        // update 修改密码,以账号作为条件 修改密码
//        User user = new User();
//        user.setAccount("zhangsan");
//        user.setPassword("666");
//        session.update("abc.changePwd", user);

        // map传参,此时Mapper的SQL中,#{ }中的值是Map的Key值
        Map<String, Object> params = new HashMap<>();
        params.put("account", "zhangsan");
        params.put("password", "9999999");
        session.update("abc.changePwd", params);

        // mybatis 关闭了自动提交,需要手动提交
        session.commit();
        session.close();
    }
}

三、日志

3.1 导入jar包

logback-classic-1.2.3.jar
logback-core-1.2.3.jar
slf4j-api-1.7.30.jar
**

3.2 编写logback.xml配置文件

<configuration>
    <!-- 将日志输出到指定位置
        ConsoleAppender 控制台
     -->
    <appender name="STDOUT"
        class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%logger{35} - %msg %n</pattern>
        </encoder>
    </appender>
    <!-- 全局设置记录日志的级别 -->
    <root level="debug"> 
        <appender-ref ref="STDOUT" /> 
    </root>
    <!-- 指定日志输出级别 additivity=false 避免日志重复打印-->
    <logger name="com.woniuxy.mapper" level="debug" additivity="false">
        <appender-ref ref="STDOUT" />
    </logger>
    <!-- 过滤无用的日志 -->
    <logger name="org.apache.ibatis.io" level="info">
        <appender-ref ref="STDOUT" />
    </logger>
</configuration>

四、分页插件

3.1 导入jar包

pagehelper-5.1.11.jar
jsqlparser-2.0.jar
**

3.2 配置拦截器

在mybatis-config.xml中,在前,配置拦截器

<!-- 引入分页插件 -->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
        </plugin>
    </plugins>

五、Mybatis实现查询

5.1 创建Goods实体类

package com.woniuxy.entity;

import java.math.BigDecimal;
import java.util.Date;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain=true) // 开启链式表达
public class Goods {
    private int id;                    //主键id
    private String name;            //商品名
    private String goodsno;            //商品编号
    private String author;            //作者
    private String publisher;        //出版社
    private String pubtime;            //发布时间
    private int categoryid;            //类别id
    private String description;        //详情
    private String image;            //商品图片
    private int stock;                //库存
    private BigDecimal marketprice;    //原价
    private BigDecimal salesprice;    //销售价
    private BigDecimal score;        //评分
    private int remarknums;            //评论数
    private Date uptime;            //上架日期
    private int salenums;            //销量
    private String newest;            //新品
    private String hot;                //热卖商品
    private String status;            //商品状态
}

注:@Accessors(chain=true)
作用:方便在属性过多的实体类中单独设置属性参数
举例:

package com.woniuxy.test;

import com.woniuxy.entity.Goods;

public class LombokTest {
    public static void main(String[] args) {
        // 链式表达
        Goods goods = new Goods().setAuthor("张三").setHot("yes");
        goods.setId(1).setStatus("1");
    }
}

5.2 编写GoodsMapper.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="goods">
  <!-- 查询所有商品 -->
  <select id="findAll" resultType="com.woniuxy.entity.Goods">
      select * from mall_goods
  </select>

  <!-- 通过商品id查询商品信息 -->
  <select id="findById" resultType="com.woniuxy.entity.Goods">
      select * from mall_goods where id = #{id}
  </select>

  <!-- 模糊查询 -->
  <select id="findByNameLike" resultType="com.woniuxy.entity.Goods">
      select * from mall_goods where name like #{name}
  </select>

  <!-- 分页查询 -->
  <select id="findByPage" resultType="com.woniuxy.entity.Goods">
      select * from mall_goods limit #{index},#{size}
  </select>

</mapper>

5.3 创建GoodsTest测试类,测试各类查询

package com.woniuxy.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.woniuxy.entity.Goods;

public class GoodsTest {

    public static void main(String[] args) throws IOException {

        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session = factory.openSession();

        // 根据id查询商品信息
//        Goods goods = session.selectOne("goods.findById", 2);
//        System.out.println(goods);

        // 根据name模糊查询商品信息
//        List<Goods> goods = session.selectList("goods.findByNameLike", "%IT%");
//        for (Goods goods2 : goods) {
//            System.out.println(goods2);
//        }

        // 分页查询
        int page = 5;
        int size = 10;
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("index", (page - 1) * size);
        params.put("size", size);
        List<Goods> goods = session.selectList("goods.findByPage", params);
        for (Goods goods2 : goods) {
            System.out.println(goods2);
        }
        session.close();
    }

}

5.4 利用分页插件进行分页查询

中已配置好分页插件,创建PageTest测试类与接收分页数据的PageUtil工具类

PageTest:

package com.woniuxy.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniuxy.entity.Goods;
import com.woniuxy.utils.PageUtil;

public class PageTest {

    public static void main(String[] args) throws IOException {

        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session = factory.openSession();

        // 设置分页的参数
        // 参数1:页码
        // 参数2:每页大小
        PageHelper.startPage(10, 5);

        // 查询数据 利用查询所有商品的SQL实现分页查询
        List<Goods> goods = session.selectList("goods.findAll");
        for (Goods goods2 : goods) {
            System.out.println(goods2);
        }

        // 获取分页信息
        PageInfo<Goods> info = new PageInfo<Goods>(goods);
        // 当前页数
        System.out.println(info.getPageNum());
        // 总页数
        System.out.println(info.getPages());
        // 总条数
        System.out.println(info.getTotal());
        // 上一页页数
        System.out.println(info.getPrePage());
        // 下一页页数
        System.out.println(info.getNextPage());

        // 将数据封装到PageUtil中,用来向浏览器返回数据
        PageUtil pageUtil = new PageUtil();
        pageUtil.setCurrentPage(info.getPageNum());
        pageUtil.setGoods(goods);
        pageUtil.setPageSize(info.getPageSize());
        pageUtil.setTotla(info.getTotal());
        pageUtil.setTotalPages(info.getPages());
        System.out.println(pageUtil);

        session.close();
    }

}

PageUtil:

package com.woniuxy.utils;

import java.util.List;

import com.woniuxy.entity.Goods;

import lombok.Data;

@Data
public class PageUtil {
    private int currentPage;     // 当前页码
    private int pageSize;         // 每一页多大
    private Long totla;         // 总条数
    private int totalPages;     // 总页数
    private List<Goods> goods;     // 当前页数据
}

注:有了分页插件后,设置好分页参数,只需要使用全查询,即可实现分页查询
**

六、mybatis执行逻辑顺序

1、首先通过输入流读取mybatis.xml与mapper.xml文件中的配置信息
2、创建session,一个session就是一次会话
3、通过selectList方法中的参数找到对应的sql语句,同时创建一个statement去查询数据库
4、查询时会得到一个ResultSet,mybatis框架根据反射自动的将得到的数据封装成pojo类对象
5、如果是selectList方法,则会自动将这些对象封装成List对象并返回