MyBatis
Mybatis是一款非常优秀的持久层框架,学习的目的是要掌握精通。
那么今天我们就来学习一下这个优秀的框架知识!
此外,由于博主的水平的原因,文章的质量可能不会太高,请酌情观看。如果大家对这篇博客里的某些地方有更好的建议,或者是发现一些问题,亦或是有更好的方案,欢迎评论区里留言。
== 传送门==
JDBC : JDBC的学习笔记
mysql : mysql的学习笔记
Java注解与反射 : Java的学习笔记
Maven :Maven的学习笔记
Junit : Junit的学习笔记
一、学前准备工作
- 环境:
- JDK1.8
- Mysql 5.7
- Maven 3.6.1
- IDEA
- 回顾
- JDBC
- Mysql
- Java基础
- Maven
- Junit
【注意】:SSM框架:配置文件,最好的方式 — 查官网
二、Mybatis简介
2.1 什么是Mybatis
- Mybatis是一款优秀的持久层框架
- 提供的持久层框架包括:
- SQL Maps
- Date Acess Objects(DAOS),数据持久层对象
- 提供的持久层框架包括:
- 它支持定制化的SQL、存储过程以及高级映射
- Mybatis几乎避免了所有的JDBC代码和手动设置参数以及获取结果集
- Mybatis可以使用简单的XML文档或者注解来配置和映射原生类型、接口和Java的POJO(实体类)为数据库中的数据
- Mybatis是apche的一个开源项目iBatis,2010年这个项目由apche software foundation 迁移到了 google code ,并且改名为Mybatis
- 2013年11月迁移到 Github
如何获取Mybatis
- maven仓库
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
- GitHub官网
2.2 持久化和持久层
- 数据持久化
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 持久状态:存到数据库当中
- 瞬时状态:断电即失
- 数据库(jdbc):io文件持久化(太耗费资源)
- 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
- 持久层
- 例如:DAO层、Service层、Controller层…
- 完成持久化工作的代码块
- 层界限十分明显
2.3 为什么需要Mybatis
- 方便
- 帮助程序员将数据存储到数据库当中
- 传统的JDBC代码太复杂。需要简化,框架。自动化。
- 不用Mybatis也可以。
- 优点:
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供映射标签,支持对象与数据库的orm字段关系映射
- 提供对象关系映射标签,支持对象关系组建维护
- 提供xml标签,支持编写动态sql
三、第一个Mybatis程序
学习思路(通用):搭建环境 —> 导入Mybatis —> 编写代码 —> 测试
3.1 搭建环境
- 搭建数据库
mysql> create database mybatis ;
Query OK, 1 row affected (0.00 sec)
mysql> use mybatis ;
Database changed
mysql> show tables;
Empty set (0.00 sec)
mysql> create table user(
-> id int(20) not null,
-> name varchar(233) default null ,
-> password varchar(233) default null ,
-> primary key(id));
Query OK, 0 rows affected (0.51 sec)
mysql> select * from user;
Empty set (0.03 sec)
mysql> desc user ;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id | int(20) | NO | PRI | NULL | |
| name | varchar(233) | YES | | NULL | |
| password | varchar(233) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
3 rows in set (0.07 sec)
mysql> insert into user (id , name , password) values (1 , 'kuangshen' , '123456' );
Query OK, 1 row affected (0.12 sec)
mysql> insert into user (id , name , password) values (2 , 'zhangsan' , '123456' );
Query OK, 1 row affected (0.07 sec)
mysql> insert into user (id , name , password) values (3 , 'lisi' , '123456' );
Query OK, 1 row affected (0.05 sec)
mysql> select * from user ;
+----+-----------+----------+
| id | name | password |
+----+-----------+----------+
| 1 | kuangshen | 123456 |
| 2 | zhangsan | 123456 |
| 3 | lisi | 123456 |
+----+-----------+----------+
3 rows in set (0.00 sec)
mysql> update user set password = '123890' where name='lisi';
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from user ;
+----+-----------+----------+
| id | name | password |
+----+-----------+----------+
| 1 | kuangshen | 123456 |
| 2 | zhangsan | 123456 |
| 3 | lisi | 123890 |
+----+-----------+----------+
3 rows in set (0.00 sec)
- 创建maven项目
- 创建父工程
- 导入依赖
<!-- 导入依赖 -->
<dependencies>
<!-- 加载mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
</dependency>
<!-- 加载mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 加入单元测试junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
3.2 创建一个模块
-
创建一个普通的maven项目,采用第二种方式进行创建
-
编写mybatis的核心配置文件
- 注意:在连接数据库的时候,不要忘记Test之后要从上方的schemas当中选择要应用的表
<?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 核心配置文件 --> <configuration> <!-- 环境,设置默认环境为development --> <environments default="development"> <!-- 可以添加复数的环境,这里只是加载了其中的一种 --> <environment id="development"> <!-- 事务管理用的JDBC --> <transactionManager type="JDBC"/> <!-- 数据源用的是pooled , 下面就是熟悉的配置,可以进行自定义设置--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 注意:在mysql8中还会有一个时区的配置 这里我用的是mysql5.7,所以没有什么问题 --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false & useUnicode=true & characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="20zzy100588A"/> </dataSource> </environment> </environments> </configuration>
-
编写mybatis的工具类
package com.zhang.dao.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.InputStream; // Mybatis 的工具类 public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory = null; static{ try { // 获取sqlSessionFactory的实体化对象 sqlSession String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (Exception e) { e.printStackTrace(); } } // 从 SqlSessionFactory 中获取 SqlSession // 既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。 // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
3.3 编写代码
-
实体类
package com.zhang.pojo; // 根据MybatisUtil编写Mybatis的代码块 // 和JDBC基本相同,编写代码和代码块 // 实体类 public class User { private int id ; private String name ; private String password ; // 构造方法 public User(){ } public User(int id , String name, String password){ this.id = id ; this.name = name ; this.password = password ; } // get、set方法 public int getId(){ return this.id ; } public void setId(int id){ this.id = id ; } public String getName(){ return this.name ; } public void setName(String name){ this.name = name ; } public String getPassword(){ return this.password ; } public void setPassword(String password){ this.password = password; } // toString @Override public String toString() { return "User{" + "id = " + this.id + " name = " + this.name + " password = " + this.password + " }"; } }
-
DAO层接口
package com.zhang.dao; import com.zhang.pojo.User; import java.util.List; public interface UserDao { List<User> getUserList(); }
-
接口实现类
- 由原来的UserDaoImpi转变成更为简单的xml配置文件
- 代码全部书写在xml配置文件当中
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace 绑定一个对应的DAO或者Mapper接口 --> <mapper namespace="com.zhang.dao.UserDao"> <!-- 这个空间的位置用来编写sql语句 --> <!-- select 语句 ,第一步实现接口,在后面的是返回的结果集 结果集有多种,常用的是resultType (返回单个结果) , resultMap(返回结果的集合) 接下来书写select语句即可 --> <select id = "getUserList" resultType="com.zhang.pojo.User"> select * from mybatis.user ; </select> </mapper>
3.4 测试
- 编写好的代码用junit进行单元测试
package com.zhang.dao;
import com.zhang.pojo.User;
import com.zhang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test(){
// 获取Session对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 方式一:执行SQL语句
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
}
}
出现的错误:org.apache.ibatis.binding.BindingException: Type interface com.zhang.dao.UserDao is not known to the MapperRegistry.
-
MapperRegistry
- 最开始的时候删掉的最后一行就是Mybatis的注册
- 每一个Mybatis都会有一个注册
<!-- 每一个Mapper.xml都需要在Mybatis核心配置文件中注册! --> <mappers> <mapper resource="com/zhang/dao/UserMapper.xml"/> </mappers>
出现错误:Could not find resource com/zhang/dao/mybatis-config.xml
-
第一步应当检测Mybatis核心配置文件和UserMapper的配置文件
- 看Mybatis-config.xml是否进行了注册
- 看UserMapper.xml配置的文件的位置是否出错
-
当初的maven问题:由于maven的约定大于配置,所以有可能会出现我们写的配置文件无法被导出或者生效的问题,解决方案如下:
- 将java目录和resources目录下的各种配置文件加载到target目录下
<build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
-
在加入build标签的时候,记得要把下面这个属性添加上
- 如果没加的时候报无效的字符错误,或者无法在xml文件当中加注释,建议把这个加上。
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
注意:做完操作之后一定不要忘记关闭资源!!!!!!
四、CRUD
4.1 namespace
- namespace中的包名要和Dao/Mapper接口的包名要一致
4.2 select语句
-
id : 就是对应的namespace中的方法名
-
resultType:Sql语句执行的返回值!
-
parameterType: 参数类型
-
步骤:
-
1、编写接口
// 查询所有的用户 List<User> getUserList(); // 根据id编号查询用户 User getUserById(int id); // 这里的User是返回值的类型,访问权限修饰符为默认(缺省的)
-
2、编写对应的sql语句
<!-- 这个空间的位置用来编写sql语句 --> <!-- select 语句 ,第一步实现接口,在后面的是返回的结果集 结果集有多种,常用的是resultType (返回单个结果) , resultMap(返回结果的集合) 接下来书写select语句即可 --> <!-- 下面的这个resultType应当返回到接口的原生类的全域名 --> <select id = "getUserList" resultType="com.zhang.pojo.User"> select * from mybatis.user <!-- 注意结尾不能加分号 --> </select> <select id="getUserById" parameterType="int" resultType="com.zhang.pojo.User"> select * from mybatis.user where id = 1 <!-- 注意结尾不能有分号 --> </select>
-
3、测试
// 多个地方使用到了创建对象,所以将对象的作用域提前 private SqlSession sqlSession = MybatisUtil.getSqlSession(); /** * 注意: 创建对象的过程因为作用域的问题,无法通过一个public方法传递到另一个public方法 * 所以,创建对象不可以封装成方法加@Before的注解 * */ @After // 每次都要关闭资源,将资源关闭封装成方法 public void close(){ sqlSession.close(); } @Test // 测试获取所有对象的方法 public void getUserListTest(){ // 获取Mapper下的类 UserMapper mapper = sqlSession.getMapper(UserMapper.class); // 实现具体的方法 List<User> userList = mapper.getUserList(); // 打印输出结果 for (User user : userList) { System.out.println(user); } } @Test public void getUserByIdTest(){ UserMapper mapper = sqlSession.getMapper(UserMapper.class); User userById = mapper.getUserById(1); System.out.println(userById); }
-
4.3 insert语句
<!-- 对象中的属性,可以直接取出来 -->
<insert id="addUser" parameterType="com.zhang.pojo.User">
<!-- #{} : 是占位符 , 用于占领一个位置 。
大括号里面的内容是参数的名称
-->
insert into mybatis.user (id, name, password) values (#{id},#{name},#{password})
</insert>
4.4 update语句
<update id="updateUser" parameterType="com.zhang.pojo.User">
update mybatis.user set name = #{name} ,password = #{password} where id = #{id}
</update>
4.5 delete语句
<delete id="deleteUser" parameterType="com.zhang.pojo.User">
delete from mybatis.user where id = #{id}
</delete>