欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

简单快速了解mybatis原理基础知识

时间:2023-06-07
Mybatis

环境:JDK 1.8 Mysql 5.7 maven 3.6.1 IDEA

回顾:JDBC Mysql Java基础 Maven Junit

SSM框架:配置文件。最好的方式:看官网文档

TK.Mybatis:持久层:Foreach、结果集处理、事务、mapper映射、mapper扫描

1、Mybatis简介 1.1 什么是Mybatis?

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

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

MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

MyBatis本是apache的一个开源项目iBatis,2010年这个项目由apache software foundation迁移到了[google code](https://baike.baidu.com/item/google code/2346604),并且改名为MyBatis。2013年11月迁移到Github。

1.2 数据持久化

持久化就是将程序中的数据在持久状态和瞬时状态转化的过程内存:断电即失 1.3 持久层

Dao层, Service层, Controller层

完成持久化工作的代码块层界限十分明显 1.4 为什么需要MyBatis? 方便传统的JDBC代码太复杂了,简化。框架。自动化帮助程序员将数据存入到数据库中不用mybatis也可以。技术没有高低之分,只有使用技术的人有高低之分。优点:

简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。提供映射标签,支持对象与数据库的orm字段关系映射。提供对象关系映射标签,支持对象关系组建维护。提供xml标签,支持编写动态sql。重要的一点是:很多人都在用mybatis。 1.5 maven版本

org.mybatis mybatis 3.5.2

1.6 中文文档:

https://mybatis.org/mybatis-3/zh/index.html

1.7 GitHub:

https://github.com/mybatis/mybatis-3

2、第一个Mybatis程序

思路:搭建环境–>导入mybatis–>编辑代码–>测试

2.1 搭建环境

//创建数据库create database `mybatis`;//使用mybatis数据库use `mybatis`;//创建user表create table `user`( `id` int(10) not null primary key, `name` varchar(20) null, `pwd` varchar(20) null)engine=innodb default charset=utf8;//想user表中插入数据insert into `user`(`id`,`name`,`pwd`) values(1,'张三','123'),(2,'李四','456'),(3,'王五','789');

2.2 新建项目(导入mybatis)

创建一个maven项目

删除src目录

导入maven依赖,在pom.xml文件中导入

mysql mysql-connector-java 5.1.47 org.mybatis mybatis 3.5.2 junit junit 4.12 test 2.3 编写代码

2.3 创建一个模块

编写mybatis核心配置文件,在resources目录中新建配置文件mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>

编写mybatis工具类

package com.ccy.utils;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;public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { //文件的路径 String resource = "mybatis-config.xml"; //MyBatis 包含一个名叫 Resources 的工具类,它包含一些实用方法,使得从类路径或其它位置加载资源文件更加容易。 InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。 // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 public static SqlSession getSqlSession(){ SqlSession sqlSession = sqlSessionFactory.openSession(); return sqlSession; }}

2.4 编写代码

实体类

package com.ccy.pojo;public class User { private int id; private String name; private String pwd; public User() { } public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } 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接口

public interface UserDao { List getUserList();}

实现类,将UserDaolmpl转化为Mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?> select * from mybatis.user

测试

@Testpublic void test(){ //第一步:获取SqlSession对象 SqlSession sqlSession = mybatisUtils.getSqlSession(); //方式一:getMapper //执行sql,getMapper可以映射出一个接口的class对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //执行getUserList方法 List userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } //关闭SqlSession sqlSession.close();}

3.3 insert

编写接口

//insert一个用户int addUser(User user);

编写对应的sql语句

insert into mybatis.user (id,name,pwd) values(#{id},#{name},#{pwd});

测试

@Testpublic void addUser(){ //第一步:获取SqlSession对象 SqlSession sqlSession = mybatisUtils.getSqlSession(); //方式一:getMapper //执行sql,getMapper可以映射出一个接口的class对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //执行getUserList方法 int ins = mapper.addUser(new User(5, "老七", "98747")); //提交事务 sqlSession.commit(); if(ins>0){ System.out.println("插入成功!"); } //关闭SqlSession sqlSession.close();}

3.4 update

编写接口

//update一个用户int updateUser(User user);

编写对应的sql语句

update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id};

测试

@Testpublic void updateUser(){ //第一步:获取SqlSession对象 SqlSession sqlSession = mybatisUtils.getSqlSession(); //方式一:getMapper //执行sql,getMapper可以映射出一个接口的class对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //执行getUserList方法 int ins = mapper.updateUser(new User(5, "老一", "98747")); //提交事务 sqlSession.commit(); if(ins>0){ System.out.println("修改成功!"); } //关闭SqlSession sqlSession.close();}

3.5 delete

编写接口

//delete一个用户idint deleteUser(int i);

编写对应的sql语句

delete from mybatis.user where id=#{id};

测试

@Testpublic void deleteUser(){ //第一步:获取SqlSession对象 SqlSession sqlSession = mybatisUtils.getSqlSession(); //方式一:getMapper //执行sql,getMapper可以映射出一个接口的class对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //执行getUserList方法 int ins = mapper.deleteUser(3); //提交事务 sqlSession.commit(); if(ins>0){ System.out.println("删除成功!"); } //关闭SqlSession sqlSession.close();}

注意:增删改一定要提交事务

3.6 出现的错误

增删改查的标签要对应起来!

错误的写法正确的写法 select * from mybatis.user where name like #{value}

测试

@Testpublic void getLike(){ //第一步:获取SqlSession对象 SqlSession sqlSession = mybatisUtils.getSqlSession(); //方式一:getMapper //执行sql,getMapper可以映射出一个接口的class对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); List userList = mapper.getLike("%李%"); for (User user : userList) { System.out.println(user); } //关闭SqlSession sqlSession.close();}

在sql语句中使用通配符!

select id,name,pwd as password from mybatis.user显示结果:User{id=1, name='张三', password='123'}User{id=2, name='李四', password='456'}User{id=3, name='老三', password='98747'}User{id=5, name='老一', password='98747'}User{id=9, name='张三', password='3415645'}User{id=10, name='张三', password='3415645'}

解决方式二:ResultMap(结果集映射)

select * from user

测试

//使用RowBounds分页@Testpublic void getLimit2(){ SqlSession sqlSession = mybatisUtils.getSqlSession(); RowBounds rowBounds = new RowBounds(0,2); //List userList = sqlSession.selectList("对应接口中的xml文件.接口中对应的方法", null, new RowBounds(0,2)); List userList = sqlSession.selectList("com.ccy.dao.UserMapper.getLimit2", null, rowBounds); System.out.println(userList); sqlSession.close();}

7.3 分页插件(了解即可)

官网:https://pagehelper.github.io/

8、使用注解开发 8.1 面向接口编程

-大家之前都学过面向对象编程,也学习过接口,但在真正开发中,很多时候我们会选择面向接口编程

-根本原因:解耦,可拓展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变得容易,规范性更好

-在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的,在这种情况下,各个对象内部是如何实现自己的,对系统设计人员来讲就不那么重要了;

-而各个对象之间的协作关系则成为系统设计的关键。小道不同类之间的通信,大到各模块之间的交互,在系统设计之初都是要着重考虑的,这也是系统设计的主要工作内容。面向接口编程就是指按照这种思想来编程。

关于接口的理解

-接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离

-接口的本身反映了系统设计人员对系统的抽象理解。

-接口应有两类:

-第一类是对一个个体的抽象,它可对应为一个抽象提(abstract class);

-第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);

-一个体有可能有多个抽象面。抽象体与抽象面是由区别的。

三个面向区别

面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法

面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现

接口设计与非接口设计师针对复用技术而言,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构

8.2 使用注解开发

1.注解在接口上实现

//使用注解@Select("select * from user")List getUsers();

2.需要在核心配置文件中绑定接口!

3.测试

@Testpublic void getUsers(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List users = mapper.getUsers(); for (User user : users) { System.out.println(user); } sqlSession.close();}本质:反射机制实现

本质:反射机制

底层:动态代理!

8.3 使用注解CRUD

使用注解可以少写接口对应的配置文件

我们可以在工具类创建的时候实现自动提交事务

public static SqlSession getSqlSession(){ //openSession的参数设置为true就是代表自动提交事务 SqlSession sqlSession = sqlSessionFactory.openSession(true); return sqlSession;}

编写接口中的sql语句

//使用注解来写sql语句@Select("select * from user")List getSelectUser();@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})")int getAddUser(User user);@Update("update user set name = #{name},pwd=#{pwd} where id = #{id}")int getUpdateUser(User user);//方法存在多个参数,参数前必须加上@Param("id")注解@Delete("delete from user where id = #{uid}")int getDeleteUser(@Param("uid") int id);

测试

public void getDeleteUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int user = mapper.getDeleteUser(2); if(user>0){ System.out.println("删除数据成功!"); } sqlSession.close();}

测试类

【注意:我们必须要将接口注册绑定到我们的核心配置文件中!】

关于@Param()注解

基本类型的参数或者String类型,需要加上

引用类型不需要加

如果只有一个基本类型的话,可以忽略,但是建议大家都加上!

我们在SQL中引用的就是我们这里的@Param(“uid”)中设定的属性名!

9、Lombok

使用步骤:

1.在IDEA中安装Lombok插件!

2.在项目中导入Lombok的jar包

org.projectlombok lombok 1.18.22 provided

常用注解:

@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。@Getter :使用方法同上,区别在于生成的是getter方法。@ToString :注解在类,添加toString方法。@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。@NoArgsConstructor: 注解在类,生成无参的构造方法。@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。@Slf4j: 注解在类,生成log变量,严格意义来说是常量。

10、多对一处理

多个学生,对应一个老师

对于学生这边而言,关联…多个学生,关联一个老师【多对一】

对于老师而言,集合,一个老师有很多学生【一对多】

测试环境搭建

CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师'); CREATE TABLE `student` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, `tid` INT(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `fktid` (`tid`), CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO `student` (`id`, `name`, `tid`) VALUES (1, '小明', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (2, '小红', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (3, '小张', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (4, '小李', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES (5, '小王', 1);

1.导入lombok

2.新建实体类 Teacher,Student

3.建立Mapper接口

4.建立Mapper.xml文件

5.在核心配置文件中绑定注册我们的Mapper接口或者文件!

6.测试查询是否能够成功!

10.1 按照查询嵌套处理

select * from teacher where id=#{id}

10.2 按照结果嵌套处理

select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where s.tid=t.id and t.id=#{tid}

11.2 按照查询嵌套处理

select * from student where tid = #{tid}

小结

1.关联- association【多对一】

2.集合-collection【一对多】

3.javaType & ofType

javaType 用来指定实体类中属性的类型ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!

注意点:

保证SQL的可读性,尽量保证通俗易懂

注意一对多和多对一中,属性名和字段的问题!

如果问题不好排查错误,可以使用日志,建议使用Log4j

面试高频

Mysql引擎

InnoDB底层原理

索引

索引优化!

12、动态SQL

什么是动态SQL:动态SQL就是指根据不同的条件生成不同的sql语句

搭建环境

CREATE TABLE blog( id varchar(50) NOT NULL COMMENT '博客id', title varchar(100) NOT NULL COMMENT '博客标题', author varchar(30) NOT NULL COMMENT '博客作者', create_time datetime NOT NULL COMMENT '创建时间', views int(30) NOT NULL COMMENT '浏览量' )ENGINE=INNODB DEFAULT charset=utf8;

步骤:

导包编写配置文件编写实体类编写实体类对应的mapper接口和mapper.xml文件 12.1 IF

select * from blog title = #{title} and author = #{author} and views= #{views}

12.3 trim(where,set)

select * from blog id = #{id}

@Testpublic void queryBlogForeach(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); ArrayList ids = new ArrayList(); ids.add(1); ids.add(2); ids.add(3); map.put("ids",ids); List blogs = mapper.queryBlogIf(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close();}

动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了

建议:

先在Mysql中写出完整的SQL,再对应的去修改成为我们的动态SQL

13、缓冲 13.1 简介

查询 : 连接数据库,耗资源!
一次查询的结果,给他暂存在一个可以直接取到的地方!---->内存 : 缓冲
我们再次查询相同数据的时候,直接走缓存,就不用走数据库了
1.什么是缓存【Cache】?

存在内存中的临时数据。

将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓冲中查询,从而提高查询效率,解决了高并发系统的性能问题。

2.为什么使用缓存?

减少和数据库的交互次数,减少系统开销,提高系统效率。

3.什么样的数据能使用缓存?

经常查询并且不经常改变的数据。 13.2 Mybatis缓存

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存

默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)

二级缓存需要手动开启和配置,他是基于namespace级别的缓存。

为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以同过实现Cache接口来自定义二级缓存

13.3 一级缓存

一级缓存也叫本地缓存:SqlSession

与数据库同一次会话期间查询到的数据会放在本地缓冲中。

以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库;

缓存失效的情况:

查询不同的东西

增删改操作,可能会改变原来的数据,所以必定会刷新缓存!

查询不同的Mapper

手动清除缓存!

SqlSession.clearCache();

小结:一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接之间

13.4 二级缓存

二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存

基于namespace级别的缓存,一个名词空间,对应一个二级缓存;

工作机制

一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;

如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;

新的会话查询信息,就可以从二级缓存中获取内容;

不同的mapper查出的数据会放在自己对应的缓存(map)中

步骤:

1.开启全局缓存

2.在要使用二级缓存的Mapper中开启

也可以自定义参数

小结:

只要开启了二级缓存,在同一个Mapper下就有效

所有的数据都会先放在一级缓存中;

只有当会话提交,或者关闭的时候,才会提交道二级缓存中!

13.5 缓存原理 13.6自定义缓存- ehcache

Ehcache 是一种广泛使用的开源Java分布式缓存。主要面向通用缓存
要在程序中使用ehcache,先要导包!

org.mybatis mybatis-ehcache 1.0.0

encache配置文件

<?xml version="1.0" encoding="UTF-8"?>

Redis数据库来做缓存! K-V

14、自我总结

mybatis创建步骤:

1.创建maven项目
在pom.xml文件中导入需要的jar包

mysql mysql-connector-java 5.1.47 org.mybatis mybatis 3.5.4 junit junit 4.13 log4j log4j 1.2.17 org.projectlombok lombok 1.18.12 compile

2.删除src文件
重新创建一个Module文件,(这样操作,创建的文新项目为子工程,jar包自动导入到子工程中);在resources中创建Mybatis-config.xml配置文件,并且导入外部数据库配置文件db.properties,log4j.properties文件为日志文件,可在配置文件中用标准日志

Mybatis-config.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>

db.propertiesdriver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8username=rootpassword=19941027log4j.properties#将登记为Debug的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码log4j.rootLogger=DEBUG,console,file#控制台输出的相关设置log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.Threshold=DEBUGlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%c]-%m%n#文件输出的相关设置log4j.appender.file = org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=./log/dong.loglog4j.appender.file.MaxFileSize=10mblog4j.appender.file.Threshold=DEBUGlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#日志输出级别log4j.logger.org.mybatis=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG

3.编写实体类User,对应的接口UserMapper以及接口配置文件UserMapper.xml
User

//导入Lombokjar包后利用注解完成getset tostring等方法@Data@AllArgsConstructor@NoArgsConstructorpublic class User { private int id; private String name; private String pwd;}

UserMapper

public interface UserMapper { List getUserList();}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

4.编写工具类utils
封装工具类MybatisUtils,用SqlSession来操作数据库

public class MybatisUtils { //获取SqlSessionFactory private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //获取SQLSession public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); }}

5.测试

public class MyTest { @Test public void test(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } //sqlSession.clearCache();//手动清除缓存 sqlSession.close(); }}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。