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>