# MybatisStudy **Repository Path**: ringo-tyl/mybatis-study ## Basic Information - **Project Name**: MybatisStudy - **Description**: Mybatis学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2021-10-11 - **Last Updated**: 2024-10-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 还原系统配置步骤: 1、下载Git 2、IDEA和Git关联 3、去仓库拉工程 4、配置Maven 5、修改主题颜色 6、修改字体大小 7、IDEA下载lombok插件 8、数据库 9、自动导包 10、快捷键调为eclipse # 一、Mybatis 3的学习 ![MyBatis logo](https://mybatis.org/images/mybatis-logo.png) ![img](https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fgit.oschina.net%2Fuploads%2Fimages%2F2016%2F0824%2F211639_4d931e7f_12260.png&refer=http%3A%2F%2Fgit.oschina.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1636335111&t=1a98e17dca204b35abdd073a61822799) ## 1.1 什么是Mybatis MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。 官网:https://mybatis.org/mybatis-3/zh/index.html 用来学习最新的API 中文网:http://www.mybatis.cn/ 用来查看使用技巧 ## 1.2 Mybatis的历史 原是apache的一个开源项目iBatis,2010年6月这个项目由apache迁移到了google code,随着开发团队转投Google code旗下,ibatis3.x正式更名为Mybatis,代码于2013年11月迁移到Github。 ## 1.3 Mybatis的优势 1. 基于sql语句编程,使用灵活,sql与程序代码的解耦 2. 与JDBC相比减少50%代码,减少大量冗余代码,不需要手动开关连接 3. 只要支持jdbc的数据库都支持Mybatis 4. 与spring集成 5. 支持面向对象编程,对象与ORM表映射 # 二、Mybaits环境搭建 ## 2.1 创建数据库和表 ```sql /* SQLyog Ultimate v12.09 (64 bit) MySQL - 5.5.54 : Database - mybatis ********************************************************************* */ /*!40101 SET NAMES utf8 */; /*!40101 SET SQL_MODE=''*/; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/`mybatis` /*!40100 DEFAULT CHARACTER SET utf8 */; USE `mybatis`; /*Table structure for table `users` */ DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `u_id` BIGINT(18) NOT NULL AUTO_INCREMENT, `u_name` VARCHAR(30) NOT NULL COMMENT '用户名', `u_pass` VARCHAR(100) NOT NULL COMMENT '密码', PRIMARY KEY (`u_id`) ) ENGINE=INNODB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; /*Data for the table `users` */ insert into `users`(`u_id`,`u_name`,`u_pass`) values (1,'张三','9033241'),(2,'李四','3333241'),(3,'王五','12156241'),(4,'赵六','1111'),(5,'铁蛋','23233241'); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; ``` ## 2.2 创建Maven工程 ![image-20211009103139363](mybatis3.assets/image-20211009103139363.png) ## 2.3 IDEA自带数据库管理工具 ![image-20211009103816538](mybatis3.assets/image-20211009103816538.png) ## 2.4 配置Maven ![image-20211009105236094](mybatis3.assets/image-20211009105236094.png) ## 2.5 创建表映射类PO ```java package com.xxgc.mybatis.po; /* alt + insert 生成构造函数 */ public class User { private long uId; private String uName; private String uPass; public long getuId() { return uId; } public void setuId(long uId) { this.uId = uId; } public String getuName() { return uName; } public void setuName(String uName) { this.uName = uName; } public String getuPass() { return uPass; } public void setuPass(String uPass) { this.uPass = uPass; } } ``` ## 2.6 创建Mybaits配置文件 ```xml ``` ## 2.7 创建一个工具类来获取SqlSession ```java package com.xxgc.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; //Mybaits工具类,用来获取sqlSession public class MyBatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { //以下三步通过配置文件来获取sqlSessionFactory String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); /* ctrl + alt + f 提取/抽取 全局变量 */ sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e){ e.printStackTrace(); } } public static SqlSession getSqlSession(){ /* ctrl + alt + v 自动生成返回结果 */ SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession; } } ``` ## 2.8 创建Dao层接口 ```java package com.xxgc.mybatis.dao; import com.xxgc.User; import java.util.List; //用户表Dao层接口 public interface UserDao { //查询所有用户 List selectAllUsers(); } ``` ## 2.9 创建映射文件 ```xml ``` ```java @Test public void test(){ //调用工具类 得到sqlSession SqlSession sqlSession = MyBatisUtils.getSqlSession(); //加载dao层映射 UserDao mapper = sqlSession.getMapper(UserDao.class); //通过调用接口执行语句 List users = mapper.selectAllUsers(); //循环打印内容 for (User user : users) { System.out.println("user = " + user); } //手动关闭sqlsession(学到了spring过后就不需要了) sqlSession.close(); } ``` 添加Mapper映射 ```xml ``` 开启驼峰命名 ```xml ``` ### 工程环境目录结构 http://www.shijiayi.top/article/268.html?t=1634010066341 # 三、Mybatis增删改查 ## 3.1 select select标签属性 - id 相应dao层方法 - parameterType 传入参数类型 - resultType 返回对象 ```xml ``` ## 3.2 insert 需要提交事务 ```java sqlSession.commit(); ``` ```xml insert into users(u_name,u_pass) value (#{uName},#{uPass}); ``` ## 3.3 update 需要提交事务 ``` sqlSession.commit(); ``` ```xml update users set u_name = #{uName},u_pass = #{uPass} where u_id = #{uId}; ``` ## 3.4 delete 需要提交事务 ``` sqlSession.commit(); ``` ```xml delete from users where u_id = #{uId}; ``` ## 3.5 特殊使用 在参数不确定的情况下,可以使用Map集合来进行参数传递 ```java //特殊的参数传递 int addUserByMap(Map map); ``` ```xml insert into users(u_name,u_pass) value (#{myName},#{myPass}); ``` ```java Map map = new HashMap(); map.put("myName","阿强"); map.put("myPass","156165156"); int i = mapper.addUserByMap(map); ``` ### 模糊查询 like查询有点特殊需要用到CONCA()函数 ```xml ``` # 三、常用配置 ## 3.1 mybatis环境配置 ```xml ``` MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置; **不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。** ## 3.2 MyBatis自动扫描Bean类 ```xml ``` ## 3.3 映射器(mappers) 既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 `file:///` 形式的 URL),或类名和包名等。例如: ```xml ``` ## 3.4 MyBatis生命周期 ![image-20211014091204372](README.assets/image-20211014091204372.png) #### SqlSessionFactoryBuilder 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 #### SqlSessionFactory 相当于一个饮料工厂,用于生产SqlSession。 被创建后在应该在程序运行期间一直存在(使用静态单例模式)。 #### SqlSession 使用后必须关闭。(饮料瓶有限,不归还无法继续生产。饮料瓶数量等于mysql最大连接数) 作用于最好是在方法层面。 ## 3.5 ResultMap(结果集/结果图) 创建表 ```sql CREATE TABLE `money` ( `m_id` bigint(18) NOT NULL AUTO_INCREMENT COMMENT '金额表id', `m_user_id` bigint(18) NOT NULL COMMENT '用户id', `m_money` int(11) NOT NULL DEFAULT '0' COMMENT '金额', `m_type` varchar(200) NOT NULL DEFAULT '人民币' COMMENT '钱的类型', PRIMARY KEY (`m_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ``` 创建触发器 ```sql DELIMITER $$ CREATE /*[DEFINER = { user | CURRENT_USER }]*/ TRIGGER `mybatis`.`usermoney` AFTER INSERT ON `mybatis`.`users` FOR EACH ROW BEGIN INSERT INTO `money`(`m_user_id`,`m_money`,`m_type`) VALUES (new.u_id,0,'人民币'), (new.u_id,0,'美元'), (new.u_id,0,'英镑'); END$$ DELIMITER ; ``` 创建扩展类 ```java package com.xxgc.mybatis.po.extend; //User实体类的扩展 public class UserEx { private String name; private int money; private String type; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } public String getType() { return type; } public void setType(String type) { this.type = type; } } ``` ```xml ``` ## 3.6 Log4j日志框架 Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件...等; 我们也可以控制每一条日志的输出格式,定义每一条日志信息的级别。 可以通过一个配置文件(log4j.properties)来灵活地进行配置,而不需要修改应用的代码。 ### Maven包查询 **如果访问不了需要修改DNS为 114.114.114.114 8.8.8.8** (https://mvnrepository.com/) ![image-20211014110207888](README.assets/image-20211014110207888.png) ### log4j.properties ```properties #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 log4j.rootLogger=WARN,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=[%p][%c]-%m%n #文件输出的相关设置 log4j.appender.file = org.apache.log4j.RollingFileAppender log4j.appender.file.File=C://logs/error.log log4j.appender.file.Append = true #输出门槛 log4j.appender.file.Threshold=WARM log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd HH:mm:ss}][%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 ``` mybatis配置 ```xml ``` 常见的日志等级 ERROR、WARN、INFO、DEBUG - ERROR 为严重错误 主要是程序的错误 - WARN 为一般警告,比如session丢失 - INFO 为一般要显示的信息,比如登录登出 - DEBUG 为程序的调试信息 ### 简单使用 ```java private Logger logger = Logger.getLogger(类名.class); ``` ```java logger.debug("调试日志"); logger.info("信息日志"); logger.warn("警告日志"); logger.error("错误日志"); ``` # 四、分页 ## 4.1 limit ```sql select * from users limt 5 #从0到5 select * from users limit 1,5 #从第一条到第五条 ``` ## 4.2 PageHelper分页插件 官网地址:https://pagehelper.github.io/ ### 添加依赖 ```xml com.github.pagehelper pagehelper 5.2.0 ``` ### Mybatis配置插件 typeAliases 之后 environments 之前 ```xml ``` ### 使用 ```java @Test public void test2(){ //调用工具类 得到sqlSession SqlSession sqlSession = MyBatisUtils.getSqlSession(); //加载dao层映射 MoneyDao mapper = sqlSession.getMapper(MoneyDao.class); //分页第一步 调用接口之前开启分页 PageHelper.startPage(1,5); List userExes = mapper.selectUserMoneyPage(); //分页第二步,对拿到的数据进行处理 PageInfo userExPageInfo = new PageInfo(userExes); logger.info("总条数"+userExPageInfo.getTotal()); for (UserEx userEx : userExPageInfo.getList()) { System.out.println("userEx = " + userEx); } //手动关闭sqlsession(学到了spring过后就不需要了) sqlSession.close(); } ``` # 五、常用插件 ## 5.1、Lombok ```xml org.projectlombok lombok 1.18.12 provided ``` 进行简单配置 ![image-20211018160221472](README.assets/image-20211018160221472.png) 下载IDEA的Lombok的插件支持 ![image-20211018160411766](README.assets/image-20211018160411766.png) ### 使用 ```java package com.xxgc.mybatis.po; import lombok.Getter; import lombok.Setter; import lombok.ToString; /* alt + insert 生成构造函数 */ @Setter @Getter //of={"uName","uPass"} 只想要这两个字段 //exclude={"uPass"} 排除字段 @ToString(exclude={"uPass"}) public class User { private long uId; private String uName; private String uPass; } ``` ## 5.2 TableGo 偷懒工具 可以生成数据库文档 官网:http://www.tablego.cn/ # 六、注解增删改查 ## 6.1 简单使用 需要在Dao层接口上添加 @Select @Insert @Update @Delete 需要在mybatis-config.xml中配置 ```xml ``` ## 6.2 Select查询 在进行多表联合查询的时候,遇到字段不匹配可以使用 ```java @Results(id = "UserExMap", value = { @Result(column = "数据库字段名",property = "类属性名"), @Result(column = "m_money",property = "money"), @Result(column = "m_type",property = "type") }) ``` 注意:只需要配置一次,如果还需要使用的地方用 ```java @ResultMap("UserExMap") ``` ## 6.3 使用注解进行sql拼接 ### 方法一 ```java //type 类名 method方法名 @SelectProvider(type = UserProvider.class,method = "selectUser") List selectUserByAttr(@Param("uId") int uId, @Param("uName")String uName); /*内部内*/ class UserProvider{ /*自定义的方法*/ public String selectUser(Map map){ String sql = "select * from users where 1 = 1 "; if(map.get("uId") != null){ sql += "and u_id = #{uId} "; } if(map.get("uName") != null && map.get("uName") != ""){ sql += "and u_name = #{uName} "; } return sql; } } ``` ### 方法二 ```java @Select({ "" }) List selectUserByAttr2(@Param("uId") int uId, @Param("uName")String uName); ``` # 七、 Mybatis处理表关联关系 ## 7.1 一对一关系的处理 ```xml ``` ```java List selectMoneyAndUser(); ``` ```java package com.xxgc.mybatis.po; import lombok.Getter; import lombok.Setter; import lombok.ToString; //Money表的映射 @Setter @Getter @ToString public class Money { private long mId; private long mUserId; private int mMoney; private String mType; //一笔钱对应一个用户 private User user; } ``` ## 7.2 一对多关系处理 ```xml ``` ```java //查询用户顺便查询用户的Money List selectUserAndMoney(); ``` ```java package com.xxgc.mybatis.po; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.util.List; /* alt + insert 生成构造函数 */ @Setter @Getter //of={"uName","uPass"} 只想要这两个字段 //exclude={"uPass"} 排除字段 @ToString(exclude={"uPass"}) public class User { private long uId; private String uName; private String uPass; private List moneyList; } ``` # 八、Sql条件查询 创建news表 ```sql CREATE TABLE `news` ( `n_id` bigint(18) NOT NULL AUTO_INCREMENT COMMENT '新闻id', `n_title` varchar(300) NOT NULL COMMENT '新闻标题', `n_content` varchar(1000) NOT NULL COMMENT '新闻内容', `n_author` varchar(30) NOT NULL COMMENT '作者', PRIMARY KEY (`n_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='新闻表' ``` ## 8.1 if标签 ```xml ``` 判断一个属性值是否为空,来拼接sql语句 ## 8.2 where标签 ```xml ``` 用来代替传统sql语句中的where关键词,它可以在有条件的时候自动追加,没有条件的时候自动取消,可以把第一个条件的and给删除掉。 ## 8.3 choose、when、otherwise标签 ```xml and 数据库字段 = #{属性} and n_content = #{nContent} and n_author = "张三" ``` 它有点像 Java 中的 switch 语句,当有一个when执行的时候,下面的otherwise就不会执行。 **使用场景:当查询某些数据的时候,需要控制权限,什么条件都不给还是得追加一个条件。** ## 8.4 sql、include标签 ```xml SELECT * FROM `news` ``` 可以把重复的sql语句(可以加标签)放到这个sql标签里面,写上id ```xml ``` 在下面需要使用到的地方只需要写include ## 8.5 set标签 ```xml `n_title` = #{nTitle}, `n_content` = #{nContent}, `n_author` = #{nAuthor} ``` 当在做更新的时候,不知道是哪个字段进行的更新,需要使用到if判断,但是使用if判断过后会有逗号的拼接问题,可以使用标签解决。 ## 8.6 foreach标签 ```xml ``` # 九、Mybatis缓存 ### 什么是缓存? 缓存是一种数据和处理中心的一个中间件,从缓存查询可以提高效率,可以最大程度使用性能。 ### 为什么使用缓存? 减少和数据库的交互次数,减少系统开销,提高系统效率。 ### 什么样的数据能使用缓存? 经常查询并且不容易发生改变的数据。 ### mybatis缓存 - MyBatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存,缓存可以极大的提升查询效率。 - Mybatis框架默认定义了两级缓存:**一级缓存和二级缓存** 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存) 二级缓存需要手动开启和配置,他是基于namespace级别的缓存 为了提高扩展,Mybatis定义了缓存接口Cache。我们可以通过实现Cache接口来定义二级缓存 ## 9.1 一级缓存 ​ 一级缓存也叫本地缓存: ​ 与数据库在一次会话期间查询到的数据会放到缓存中。 ​ 以后如果需要获取相同数据,会直接从缓存中拿,没必要再去查询数据库。 ​ 注意: ​ 必须保证多次查询中间,不能有任何的增删改操作,否则缓存数据会清空。 ```java //手动清理缓存 sqlSession.clearCache(); ``` ## 9.2 二级缓存 ### 二级缓存使用 1、要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行: ```xml ``` 配置缓存 ```xml ``` eviction 配置缓存策略 - `LRU` – 最近最少使用:移除最长时间不被使用的对象。 - `FIFO` – 先进先出:按对象进入缓存的顺序来移除它们。 - `SOFT` – 软引用:基于垃圾回收器状态和软引用规则移除对象。 - `WEAK` – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。 flushInterval 刷新间隔 size 缓存可用空间 readOnly 只读 会返回相同实例(因为这些实例是不可修改的) readOnly 查询出来的实例是可以修改的,但是如果为false两个实例不相同。 ### 二级缓存总结: 业务逻辑层去拿数据的时候,会先看二级缓存里面有没有东西,如果有就返回,如果没有就查询,并把查询结果返回给二级缓存。 ## 9.3 Mybaits缓存插件 ehcache ```xml org.mybatis.caches mybatis-ehcache 1.2.1 ``` ```xml ``` 创建一个配置文件ehcache.xml ```xml ``` 2、开启全局缓存 ```xml ``` # 附录 ## 1.IDEA常用快捷键 ``` alt + insert 生成构造函数 ``` ``` ctrl + alt + f 提取/抽取 全局变量 ``` ``` ctrl + alt + v 自动生成返回结果 ``` ``` ctrl + alt + t 常用包裹代码生成 ``` ``` iter 生成foreach循环 ``` ## 2.IDEA配置自动导包 ![image-20211009114132613](mybatis3.assets/image-20211009114132613.png)