> 文档中心 > Mybatis(全总结)

Mybatis(全总结)


Mybatis(总结)

1.简介

1.1什么是Mybatis

1.MyBatis 是一款优秀的持久层框架。
2.它支持定制化 SQL、存储过程以及高级映射。
3.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
4.MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO为数据库中的记录。

1.2持久化

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

1.3持久层

Dao层:持久层

Service:业务操作

Controller层:接收用户的请求,并把请求转发给业务层做

1.4Mybatis的作用

1.将数据存入到数据库中

2.方便

3.传统的JDBC代码太复杂。对其进行简化

1.5Mybatis优点

1.简单易学

2.灵活

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

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

5.提供XML标签,支持编写动态sql

2.搭建Mybatis程序的步骤

2.1搭建数据库

CREATE DATABASE /*!32312 IF NOT EXISTS*/`booksys` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;USE `booksys`;/*Table structure for table `author` */DROP TABLE IF EXISTS `author`;CREATE TABLE `author` (  `authorid` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(10) NOT NULL,  `concat` varchar(100) DEFAULT NULL,  `birtday` date DEFAULT NULL,  PRIMARY KEY (`authorid`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;/*Data for the table `author` */insert  into `author`(`authorid`,`name`,`concat`,`birtday`) values(1,'张孝祥','北京海淀区','2021-11-02'),(2,'诸葛亮','西安市长安中路','2021-09-07'),(3,'曹操','河南洛阳市',NULL);/*Table structure for table `book` */DROP TABLE IF EXISTS `book`;CREATE TABLE `book` (  `bookid` int(6) unsigned zerofill NOT NULL AUTO_INCREMENT,  `bookname` varchar(100) NOT NULL,  `price` float DEFAULT NULL,  `sortname` varchar(50) DEFAULT NULL,  `summary` varchar(200) DEFAULT NULL,  `pubDate` date DEFAULT NULL,  `pubcom` varchar(60) DEFAULT NULL,  `authorid` int(11) DEFAULT NULL,  PRIMARY KEY (`bookid`),  KEY `fk_book_author` (`authorid`),  CONSTRAINT `fk_book_author` FOREIGN KEY (`authorid`) REFERENCES `author` (`authorid`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;/*Data for the table `book` */insert  into `book`(`bookid`,`bookname`,`price`,`sortname`,`summary`,`pubDate`,`pubcom`,`authorid`) values(000001,'Java实战',56,'技术开发',NULL,'2022-03-02','文都智链',1),(000002,'JavaWeb入门到提高',66,'开发',NULL,'2022-03-01','文都智链',2),(000003,'MySQL实战',64,'数据库',NULL,'2022-03-03','电子出版社',1),(000004,'Mybatis实践开发',54,'框架',NULL,'2021-08-05','清华出版社',1);

2.2新建项目

1.新建一个普通的maven项目

2.导入maven依赖

<dependencies>        <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version>    </dependency>        <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version>    </dependency>        <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version>    </dependency>        <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version>    </dependency>        <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope>    </dependency>    <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>compile</scope>    </dependency>        <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version>    </dependency>        <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.2.0</version>    </dependency></dependencies>

3.编写mybatis的核心配置文件

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <properties resource="db.properties"></properties>    <settings> <setting name="logImpl" value="STDOUT_LOGGING"/>    </settings>    <typeAliases> <typeAlias type="" alias=""></typeAlias>     </typeAliases>    <environments default="development"> <environment id="development">     <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>    </environments>    <mappers> <mapper resource=""/>     </mappers></configuration>

4.编写Mybatis工具类

package com.mybatis.util;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 java.io.IOException;import java.io.InputStream;/ * 工具类 *  SqlSession *   */public class MyBatisUtil {    private static SqlSessionFactory sessionFactory;    private final static String conf = "mybatis-config.xml";    static{ try {     InputStream is = Resources.getResourceAsStream(conf);     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();     sessionFactory = builder.build(is); } catch (IOException e) {     e.printStackTrace(); }    }    public static SqlSession getSession(boolean isAuto){ return sessionFactory.openSession(isAuto);    }    public static SqlSession getSession(){ return getSession(true);    }    public static void closeSession(SqlSession sqlSession){ if(sqlSession != null){     sqlSession.close(); }    }}

5.编写实体类

package com.mybatis.pojo;import lombok.Data;import java.io.Serializable;import java.util.Date;@Datapublic class Book  {    private Integer bookid;    private String bookname;    private Float price;    private Date pubDate;    private Author author;}

6.编写原DAO层Mapper接口

public interface IBookDao { List<Book> queryAll();}

7.编写接口实现类

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="">        <select id="">     </select></mapper>

8.进行测试

import com.mybatis.dao.IBookDao;import com.mybatis.pojo.Book;import com.mybatis.util.MyBatisUtil;import org.apache.ibatis.session.SqlSession;import org.junit.jupiter.api.Test;import java.util.List;public class TestBook {    @Test    public void testbook(){ SqlSession sqlSession = MyBatisUtil.getSession(); IBookDao iBookDao = sqlSession.getMapper(IBookDao.class); List<Book> list = iBookDao.queryAll(); list.forEach(System.out::println); MyBatisUtil.closeSession(sqlSession);    }}

3.对数据库进行增,删,改,查

3.1 namespace

namespace中的包名要和Dao/Mapper接口的包名一致

3.2 select

查询语句

  • id:就是对应namespace中接口中的方法名
  • resulttype:sql语句执行的返回值(大部分是实体类)
  • parametertype:参数的类型

1.编写接口定义的方法

/ * 查询book中所有的信息 * @return */List<Book> queryall();

2.编写对应mapper中的sql语句

<select id="queryall" resultType="book">    select * from books;</select>

3.进行测试

import com.mybatis.dao.Bookdao;import com.mybatis.pojo.Book;import com.mybatis.util.Mybatisutil;import org.apache.ibatis.session.SqlSession;import org.junit.jupiter.api.Test;import java.util.List;public class TestBook {    @Test    public void testbook(){ SqlSession sqlSession = Mybatisutil.getsqlsession(); Bookdao bookdao = sqlSession.getMapper(Bookdao.class); List<Book> list = bookdao.queryall(); list.forEach(System.out::println); Mybatisutil.closesqlsession(sqlSession);    }}

3.3 insert

1.编写接口定义的方法

/ * 添加一本书 */int addbook(Book book);

2.编写对应mapper中的sql语句

<insert id="addbook" parameterType="book">    insert into book(bookid,bookname,price,sortname) values (null,'活人克难了',150,'玄学')</insert>

3.进行测试

@Testpublic void insert(){    Book book = new Book(null,"活人克难了",150f,"社交");    SqlSession sqlSession = Mybatisutil.getsqlsession();    Bookdao bookdao = sqlSession.getMapper(Bookdao.class);    int i = bookdao.addbook(book);    System.out.println(i);    Mybatisutil.closesqlsession(sqlSession);}

3.3 delete和update类似上

3.4 Map的使用

如果我们的实体类,或者数据库中的表,字段或者参数过多,应当考虑使用Map

/ * 不知道数据库中有什么,只需要去查对应的字段 */int addbook(Map<String , Object> map);
<insert id="addbook" parameterType="map"> insert into book(bookid,bookname,price,pubdate) values (#{bookid},#{bookname},#{price},#{pubdate})    </insert>
@Testpublic void test2(){    SqlSession sqlSession = MyBatisUtil.getSession();    IBookDao iBookDao = sqlSession.getMapper(IBookDao.class);    Map<String,Object> map = new HashMap<String, Object>();    map.put("bookid",6);    map.put("bookname","爱的教育");    map.put("price",55f);    map.put("pubdate",new Date());    int i = iBookDao.addbook(map);    System.out.println(i);    MyBatisUtil.closeSession(sqlSession);}

4.日志

4.1导入log4j包

<dependency>    <groupId>log4j</groupId>    <artifactId>log4j</artifactId>    <version>1.2.17</version></dependency>

4.2在配置文件中配置

<settings>    <setting name="logImpl" value="STDOUT_LOGGING"/></settings>

5. Lombok

5.1导入Lombok包

<dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.24</version></dependency>

5.2 在实体类前加入注解即可

@Data@AllArgsConstructor@NoArgsConstructorpublic class User {    private Integer id;    private String username;    private String password;    private Integer age;    private String sex;    private String email;}

6.缓存

缓存机制减轻数据库压力,提高数据库性能

mybatis的缓存分为两级:一级缓存、二级缓存

6.1一级缓存

一级缓存为 SqlSession 缓存,是默认开启的,缓存的数据只在 SqlSession 内有效。在操作数据库的时候需要先创建 SqlSession 会话对象,在对象中有一个 HashMap 用于存储缓存数据,此 HashMap 是当前会话对象私有的,别的 SqlSession 会话对象无法访问。

具体流程:

第一次执行 select 完毕会将查到的数据写入 SqlSession 内的 HashMap 中缓存起来

第二次执行 select 会从缓存中查数据,如果 select 同传参数一样,那么就能从缓存中返回数据,不用去数据库了,从而提高了效率

注意:

1、如果 SqlSession 执行了 DML 操作(insert、update、delete),并 commit 了,那么 mybatis 就会清空当前 SqlSession 缓存中的所有缓存数据,这样可以保证缓存中的存的数据永远和数据库中一致,避免出现差异

2、当一个 SqlSession 结束后那么他里面的一级缓存也就不存在了, mybatis 默认是开启一级缓存,不需要配置

3、 mybatis 的缓存是基于 [namespace:sql语句:参数] 来进行缓存的,意思就是, SqlSession 的 HashMap 存储缓存数据时,是使用 [namespace:sql:参数] 作为 key ,查询返回的语句作为 value 保存的

6.2二级缓存

1.配置文件中配置开启二级缓存

1、conf.xml 配置全局变量开启二级缓存

<settings>    <setting name="cacheEnabled" value="true"/>默认是false:关闭二级缓存<settings>

2.映射文件开启缓存

2、在userMapper.xml中配置

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>当前mapper下所有语句开启二级缓存

这里配置了一个 LRU 缓存,并每隔60秒刷新,最大存储512个对象,而返回的对象是只读的

3.需要在缓存的实体类对象实现序列化

public class Book implements Serializable

4.禁用

若想禁用当前select语句的二级缓存,添加 useCache="false"修改如下:

<select id="getCountByName" parameterType="java.util.Map" resultType="INTEGER" statementType="CALLABLE" useCache="false">

7.动态SQL

MyBatis 的强大特性之一便是它的动态 SQL

7.1 if

<select id="findActiveBlogWithTitleLike"     resultType="Blog">  SELECT * FROM BLOG   WHERE state = ‘ACTIVE’   <if test="title != null">    AND title like #{title}  </if></select>

这条语句提供了一个可选的文本查找类型的功能。如果没有传入"title",那么所有处于"ACTIVE"状态的BLOG都会返回;反之若传入了"title",那么就会把模糊查找"title"内容的BLOG结果返回

7.2 choose,when,otherwise

MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句

<select id="findActiveBlogLike"     resultType="Blog">  SELECT * FROM BLOG WHERE state = ‘ACTIVE’  <choose>    <when test="title != null">      AND title like #{title}    </when>    <when test="author != null and author.name != null">      AND author_name like #{author.name}    </when>    <otherwise>      AND featured = 1    </otherwise>  </choose></select>

7.3 trim,where,set

<select id="findActiveBlogLike"     resultType="Blog">  SELECT * FROM BLOG   <where>     <if test="state != null">  state = #{state}    </if>     <if test="title != null"> AND title like #{title}    </if>    <if test="author != null and author.name != null"> AND author_name like #{author.name}    </if>  </where></select>

7.4 foreach

动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候

<select id="selectPostIn" resultType="domain.blog.Post">  SELECT *  FROM POST P  WHERE ID in  <foreach item="item" index="index" collection="list"      open="(" separator="," close=")"> #{item}  </foreach></select>