Mybatis笔记

环境:

  • JDK1.8

  • MySql5.7

  • Maven3.8.1

  • IDEA

回顾:

  • JDBC

  • Mysql

  • Java基础

  • Maven

  • Junit(单元测试模块)

1.简介

1.1 什么是Mybatis?

  • MyBatis 是一款优秀的持久层框架

  • 它支持自定义 SQL、存储过程以及高级映射。

  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • 中文文档:https://mybatis.org/mybatis-3/zh/getting-started.html

1.2 什么是持久化?

数据持久化

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程

为什么需要持久化?

  • 有一些对象不能丢弃

  • 内存太贵了

1.3 持久层

Dao层,Service层,Controller层

  • 完成持久化操作的代码块

  • 层界限十分明显(?)

1.4 为什么需要MyBatis

  • 方便

  • 传统的JDBC代码太复杂。简化。框架。自动化

  • 帮助程序员将数据存入到数据库中

  • 优点:

    • 简单易学

    • 灵活

    • sql和代码的分离,提高了可维护性

    • 提供映射标签,支持对象与数据库的orm字段关系映射

    • 提供对象关系映射标签,支持对象关系组建维护

    • 提供xml标签,支持边写动态的sql

最重要的一点:使用的人多

2. 第一个Mybatis程序

2.1 搭建环境

创建数据库

SHOW TABLES;
​
CREATE TABLE `user`(
 `id` INT(20) NOT NULL,
 `name` VARCHAR(30) NOT NULL,
 `pwd` VARCHAR(30) NOT NULL,
 PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
​
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES
(1,"Test1","123456"),
(2,"Test2","123456"),
(3,"Test3","123456");

创建Maven项目,导入mysql驱动,mybatis,Junit依赖

2.2 创建Mybatis配置文件

<?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"/>
           <dataSource type="POOLED">
               <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
               <property name="url"
                         value="jdbc:mysql://127.0.0.1:3306/Mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;"/>
               <property name="username" value="mouzhai"/>
               <property name="password" value="mouzhai"/>
           </dataSource>
       </environment>
​
   </environments>
​
   <!--配置好Mappers标签 Mybatis才知道去哪里找mapper映射文件-->
   <!--有三种配置方法:
       resource="cn/zhaiblog/dao/UserMapper.xml"
       class="cn.zhaiblog.dao.UserMapper"
       url="绝对路径 不会"
   -->
   <mappers>
       <mapper class="cn.zhaiblog.dao.UserMapper"/>
   </mappers>
</configuration>
  • 编写Mybatis工具类

    //工具类 获取sqlSessionFactory --> sqlSession
    public class MybatisUtils {
       private static SqlSessionFactory sqlSessionFactory;
    ​
       static {
           //使用Mybatis获取sqlSessionFactory对象
           String resource = "mybatis-config.xml";
           try {
               InputStream resourceAsStream = Resources.getResourceAsStream(resource);
               sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
          } catch (IOException e) {
               e.printStackTrace();
          }
      }
    ​
       public static SqlSession getSqlSession(){
           if (sqlSessionFactory!=null){
               return sqlSessionFactory.openSession();
          }
           return null;
      }
    }

2.3 编写代码

  • 实体类

package cn.zhaiblog.pojo;
​
/**
* 实体类
*/
public class User {
   private int id;
   private String name;
   private String pwd;
​
   public User(int id, String name, String pwd) {
       this.id = id;
       this.name = name;
       this.pwd = pwd;
  }
​
   public User() {
  }
​
   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;
  }
​
   public String getPwd() {
       return pwd;
  }
​
   public void setPwd(String pwd) {
       this.pwd = pwd;
  }
​
   @Override
   public String toString() {
       return "User{" +
               "id=" + id +
               ", name='" + name + '\'' +
               ", pwd='" + pwd + '\'' +
               '}';
  }
}
  • Dao接口

package cn.zhaiblog.dao;
​
import cn.zhaiblog.pojo.User;
​
import java.util.List;
​
public interface UserDao {
   List<User> getUserList();
}
  • 接口实现类(由原来的UserImpl转换为xml配置文件 UserMapper)

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--Namespace绑定一个dao/mapper接口-->
<mapper namespace="cn.zhaiblog.dao.UserMapper">
   
   <!--查询语句 id:必须有,对应UserImpl实现类中的方法名   resultType返回类型:要是完整路径-->
   <select id="getUserList" resultType="cn.zhaiblog.pojo.User">
      select *
      from mybatis.user
   </select>
</mapper>

2.4 测试

注意点:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.zhaiblog.dao.UserMapper.getUserList

3. CRUD

Select

<!--
   查询语句 id:必须有,对应UserImpl实现类中的方法名   resultType返回类型:要是完整路径 可以使用别名
如果是多个对象,用list封装,这里resultType也不用改成List,用对象即可
-->
<select id="getUserList" resultType="cn.zhaiblog.pojo.User">
  select *
  from mybatis.user
</select>

insert

<insert id="addUser" parameterType="cn.zhaiblog.pojo.User">
  insert into user(id, name, pwd)
  VALUES (#{id}, #{name}, #{pwd})
</insert>

update

<update id="updateUser" parameterType="cn.zhaiblog.pojo.User">
  update user
  set name = #{name},
      pwd = #{pwd}
  where id = #{id};
</update>

delete

<delete id="deleteUser" parameterType="int">
  delete
  from user
  where id = #{id};
</delete>

4. 配置解析

4.1 核心配置文件

  • mybatis-config.xml

  • MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:

configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

4.2 环境配置(environments)

尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。

  • 默认使用的环境 ID(比如:default=”development”)。

  • 每个 environment 元素定义的环境 ID(比如:id=”development”)。

  • 事务管理器的配置(比如:type=”JDBC”)。

  • 数据源的配置(比如:type=”POOLED”)。

事务管理器(transactionManager)

在 MyBatis 中有两种类型的事务管理器(也就是 type=”[JDBC|MANAGED]”):

  • JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。

  • MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为

数据源(dataSource)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。

  • 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。

有三种内建的数据源类型(也就是 type=”[UNPOOLED|POOLED|JNDI]”):

UNPOOLED:无连接池 对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。

POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。

JNDI:springboot自带连接池

4.3 属性(Properties)

<!--引入配置文件代替dataSource里的Property-->
<properties resource="db.properties">
   <property name="username" value="mouzhai"/>
</properties>
​
<environment id="test">
   <transactionManager type="JDBC"/>
   <dataSource type="POOLED">
       <property name="driver" value="${driver}"/>
       <property name="url"
                 value="${url}"/>
       <property name="username" value="${username}"/>
       <property name="password" value="${password}"/>
   </dataSource>
</environment>

4.4 类型别名(TypeAliases)

可以在xml中配置标签

<!--一个个定义别名-->
<typeAliases>
   <typeAlias type="cn.zhaiblog.pojo.User" alias="User"></typeAlias>
</typeAliases>
​
​
<!--自定义包扫描 实体类非常多的时候推荐-->
<typeAliases>
   <package name="cn.zhaiblog.pojo"/>
</typeAliases>

也可以在类上面加注解

@Alias("User")
public class User {
   private int id;
   private String name;
   private String pwd;
}

4.5 映射器(Mapper)

<!--配置好Mappers标签 Mybatis才知道去哪里找mapper映射文件-->
<!--有四种配置方法:
   resource="cn/zhaiblog/dao/UserMapper.xml"
   class="cn.zhaiblog.dao.UserMapper"
   url="绝对路径 不用它"
<package name = "">
-->
<mappers>
   <mapper class="cn.zhaiblog.dao.UserMapper"/>
</mappers>
​
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
 <package name="cn.zhaiblog.dao"/>
</mappers>
  • 接口和他的Mapper配置必须同名

  • 接口和他的mapper文件必须在同一个包下!

5. 解决属性名和字段名不一致的问题

5.1 方法一

/**
* 实体类
*/
public class User {
   private int id;
   private String name;
   private String password;
}
// 给sql语句起个别名就可以了
<select id="getUserByID" resultType="User" parameterType="_int">
  select id, name, pwd as password
  from user
  where id = #{id};
</select>

10d569008f0f

5.2 方法二 resultMap

结果集映射 resultMap 元素是 MyBatis 中最重要最强大的元素.

<!-- id就是名称 type就是映射出来的类型 -->
<resultMap id="UserMap" type="User">
   <!--colnum数据库中的字段,property实体类中的属性-->
   <result column="pwd" property="password"/>
</resultMap>
​
​
<select id="getUserByID" resultMap="UserMap" parameterType="_int">
  select *
  from user
  where id = #{id};
</select>

阿里巴巴规范手册推荐

规范手册推荐,不管是pojo类和查询结果字段是否匹配,一律使用resultMap映射,这样可以解耦,一个map对应一个查询

6. 日志

6.1 日志工厂

如果一个数据库操作,出现了异常,我们需要拍错,日志就是最好的助手!

曾经:sout , debug

现在:日志工厂

a7d798d3b5fb

  • SLF4J

  • LOG4J(deprecated since 3.5.9)

  • LOG4J2

  • JDK_LOGGING

  • COMMONS_LOGGING

  • STDOUT_LOGGING

  • NO_LOGGING

<!-- 标准的日志工厂实现 -->
<settings>
   <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

8cc704f7a243

6.2 log4j

  1. 导入log4j

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
   <version>1.2.17</version>
</dependency>
  1. 配置文件

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
    log4j.rootLogger=DEBUG,console,file
    ​
    #控制台输出的相关设置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    ​
    #文件输出的相关设置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/zhai.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    ​
    #日志输出级别
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
  2.  简单实用
    Logger logger = Logger.getLogger(UserMapperTest.class);
    ​
    @Test
    public void Log4jTest() {
       logger.info("info:进入了Log4JTest");
       logger.debug("debug:进入了Log4JTest");
       logger.error("error:进入了Log4JTest");
    }
  3. 运行结果

cfe8fe5e9abf

7. 分页

思考:为什么要分页?

  • 减少数据量

从startIndex开始查,每页显示pageSize个
语法:SELECT * FROM user limit startIndex,pageSize;

8. 多对一查询

方法一:子查询

<!--思路:
       1: 查询所有的学生
       2: 根据查询出来的学生tid,寻找对应的老师
-->
<select id="getAllStudent" resultMap="studentToTeacher">
  select *
  from student;
</select>
​
<resultMap id="studentToTeacher" type="cn.zhaiblog.pojo.Student">
   <result property="id" column="id"/>
   <result property="name" column="name"/>
   <!--accociation 表示对象 collection 表示集合-->
   <association property="teacher" column="tid" javaType="cn.zhaiblog.pojo.Teacher" select="getAllTeacher"/>
</resultMap>
​
<select id="getAllTeacher" resultType="cn.zhaiblog.pojo.Teacher">
  select *
  from teacher;
</select>

方法二:嵌套查询

<select id="getAllStudent" resultMap="studentToTeacher">
  select s.id sid, s.name sname, s.tid stid, t.id tid, t.name tname
  from student s,
        teacher t
  where s.tid = t.id;
</select>
​
<resultMap id="studentToTeacher" type="cn.zhaiblog.pojo.Student">
   <result property="id" column="sid"/>
   <result property="name" column="sname"/>
   <association property="teacher" javaType="cn.zhaiblog.pojo.Teacher">
       <result property="name" column="tname"/>
   </association>
</resultMap>

回顾Mysql多对一查询方式:

  • 子查询

  • 连表查询

9. 一对多查询(待续)

10. 动态SQL(待续)

11. 缓存(待续)

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容