一、了解MyBatis
1、历史(百度百科)
- MyBatis 本是apache的一个开源项目【iBatis】, 2010年这个项目由apache software foundation(Apache软件基金会) 迁移到了google code(谷歌的代码托管平台),并且改名为MyBatis ,2013年11月迁移到Github。
2、作用 (百度百科)
- MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
3、说说持久化
持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。
- 程序产生的数据首先都是在内存。
- 内存是不可靠的,他丫的一断电数据就没了。
- 那可靠的存储地方是哪里?硬盘、U盘、光盘等。
- 我们的程序在运行时说的持久化通常就是指将内存的数据存在硬盘。
4、说说持久层
其实分层的概念已经谈到过:
- 业务是需要操作数据的
- 数据是在磁盘上的
- 具体业务调用具体的数据库操作,耦合度太高,复用性太差
- 将操作数据库的代码统一抽离出来,自然就形成了介于业务层和数据库中间的独立的层
5、聊聊ORM
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。
- jpa(Java Persistence API)是java持久化规范,是orm框架的标准,主流orm框架都实现了这个标准。
- hibernate:全自动的框架,强大、复杂、笨重、学习成本较高,不够灵活,实现了jpa规范。Java Persistence API(Java 持久层 API)
- MyBatis:半自动的框架(懂数据库的人 才能操作) 必须要自己写sql,不是依照的jpa规范实现的。
很多人青睐 MyBatis ,原因是其提供了便利的 SQL 操作,自由度高,封装性好...... JPA对复杂 SQL 的支持不好,没有实体关联的两个表要做 join ,的确要花不少功夫。
6、MyBatis的优点和缺点
-
sql语句与代码分离,存放于xml配置文件中:
优点:便于维护管理,不用在java代码中找这些语句;
缺点: JDBC方式可以用打断点的方式调试,但是MyBatis调试比较复杂,一般要通过log4j日志输出日志信息帮助调试,然后在配置文件中修改。
-
用逻辑标签控制动态SQL的拼接:
优点:用标签代替编写逻辑代码;
缺点:拼接复杂SQL语句时,没有代码灵活,拼写比较复杂。不要使用变通的手段来应对这种复杂的语句。
-
查询的结果集与java对象自动映射:
优点:保证名称相同,配置好映射关系即可自动映射或者,不配置映射关系,通过配置列名=字段名也可完成自动映射。
缺点:对开发人员所写的SQL依赖很强。
-
编写原生SQL:
优点:接近JDBC,比较灵活。
缺点:对SQL语句依赖程度很高;并且属于半自动,数据库移植比较麻烦,比如MySQL数据库编程Oracle数据库,部分的SQL语句需要调整。
-
最重要的一点,使用的人多!公司需要!
二、搭建个环境
1、建立数据库
sql
CREATE DATABASE `ssm`;
USE `ssm`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(20) NOT NULL,
`username` varchar(30) DEFAULT NULL,
`password` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`username`,`password`) values (1,'itnanls','123456'),(2,'itlils','abcdef'),(3,'ydlclass','987654');
2、构建一个父工程
尝试学习聚合工程的规范,当然可以搭建独立的工程,我们选择一个比较新的jdk版本11:
将父工程的打包方式修改成pom,表示一个聚合工程:
xml
<packaging>pom</packaging>
#3、父工程的maven配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ydlclass</groupId>
<artifactId>ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 父模块用于约束版本信息 -->
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>4.13.1</junit.version>
<mybatis.version>3.5.7</mybatis.version>
<mysql-connector-java.version>8.0.26</mysql-connector-java.version>
<lombok.version>1.18.22</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- mybatis 核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- 数据库确定 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
4、创建子模块
pom
xml
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- 处理资源被过滤问题 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${maven.compiler.target}</source> <!-- 源代码使用的JDK版本 -->
<target>${maven.compiler.target}</target> <!-- 需要生成的目标class文件的编译版本 -->
<encoding>UTF-8</encoding><!-- 字符集编码 -->
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
5、回顾我们的jdbc代码
ini
@Test
public void testConnection1() throws Exception{
//1.数据库连接的4个基本要素:
String url = "jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "root";
//8.0之后名字改了 com.mysql.cj.jdbc.Driver
String driverName = "com.mysql.cj.jdbc.Driver";
//2.实例化Driver
Class clazz = Class.forName(driverName);
Driver driver = (Driver) clazz.newInstance();
//3.注册驱动
DriverManager.registerDriver(driver);
//4.获取连接
Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement preparedStatement = conn.prepareStatement("select * from user where id = ?");
preparedStatement.setInt(1,1);
ResultSet resultSet = preparedStatement.executeQuery();
// 处理结果集
while (resultSet.next()){
User user = new User();
user.setId(resultSet.getInt("id"));
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
System.out.println(user);
}
}
6、编写MyBatis核心配置文件,mybatis-config.xml
有兴趣的自行深入研究。
- UNPOOLED:不使用连接池的数据源
- POOLED:使用连接池的数据源
- JNDI:使用JNDI实现的数据源,我们在学习JavaEE的时候学习过了
配置文件我们从官网复制:mybatis.org/mybatis-3/z...
xml
<?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>
<properties>
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
<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>
</configuration>
小知识:
#(1)DTD:
DTD(Document Type Definition)即文档类型定义,是一种XML约束模式语言,是XML文件的验证机制
如下所示是公共DTD示例。
xml
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
关于DTD的声明解释如下:
1、DTD声明始终以!DOCTYPE开头,空一格后跟着文档根元素的名称。
2、根元素名:configuration。所以每一个标签库定义文件都是以taglib为根元素的,否则就不会验证通过。
3、PUBLIC "-//mybatis.org//DTDopen in new window Config 3.0//EN,这是一个公共DTD的名称(私有的使用SYSTEM表示)。这个东西命名是有些讲究的。首先它是以"-"开头的,表示这个DTD不是一个标准组织制定的。(如果是ISO标准化组织批准的,以"ISO"开头)。接着就是双斜杠"//",跟着的是DTD所有者的名字,很明显这个DTD是MyBatis公司定的。接着又是双斜杠"//",然后跟着的是DTD描述的文档类型,可以看出这份DTD描述的是DTD Config 3.0的格式。再跟着的就是"//"和ISO 639语言标识符。
4、绿色的字"mybatis.org/dtd/mybatis...",表示这个DTD的位置。
疑问:是不是xml分析器都会到java.sun.com上去找这个dtd呢?答案是否定的,xml分析器首先会以某种机制查找公共DTD的名称,查到了,则以此为标准,如果查不到,再到DTD位置上去找。
(2)XSD
文档结构描述XML Schema Definition 缩写,这种文件同样可以用来定义我们xml文件的结构!
我们看看pom文件的xml头部:
ini
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd
">
1、第一行的xmlns代表了一个xml文件中的一个命名空间,通常是一个唯一的字符串,一般使用一个url,因为不会重复嘛。
它的语法如下:
ini
xmlns:namespace-prefix="namespaceURI"
后边什么也不加,代表默认命名空间,我们在书写标签的时候不需要加任何前缀。
如果我将其改为:
ini
xmlns:c="http://maven.apache.org/POM/4.0.0"
image-20211104144031737
2、xmlns:xsi 定义了一个命名空间前缀 xsi 对应的唯一字符串 www.w3.org/2001/XMLSch... xmlns:xsi 在不同的 xml 文档中似乎都会出现。 这是因为, xsi 已经成为了一个业界默认的用于 XSD((XML Schema Definition) 文件的命名空间。 而 XSD 文件(也常常称为 Schema 文件)是用来定义 xml 文档结构的。剩余两行的目的在于为我们的命名空间指定对应的xsd文件。
事实上我们这么写也是可以的:
image-20211104144300243
上面这行的语法其实是, xsi:schemaLocation = "ns1url xsd1 ns2url xsd2"
XML Schema相对于DTD的优点在于:
- XML Schema基于XML,没有专门的语法。
- XML Schema可以像其他XML文件一样解析和处理。
- XML Schema比DTD提供了更丰富的数据类型。
- XML Schema提供可扩充的数据模型。
- XML Schema支持综合命名空间。
- XML Schema支持属性组。
7、lombok
平时的工作中写setter和getter以及toString方法是不是已经烦了,每次添加一个字段都要重新添加这些方法。
今天我们学习一个神器,从此再也不用写这些重复的代码了,它们在编译的时候动态的帮我们生成这些代码。
- javac对源代码进行分析,生成了一棵抽象语法树(AST)
- 运行过程中调用实现了"JSR 269 API"的Lombok程序
- 此时Lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
- javac使用修改后的抽象语法树(AST)生成字节码文件,即给class增加新的节点(代码块)
1,首先,我们必须安装一个插件,否则编译的时候会报错,你没有写setter方法,又去调用它当然不能编译:
image-20211020113926489
2、引入依赖,lombok在编译的时候,会根据我们的注解动态生成我们需要的构造方法,setter和getter等,运行的时候就没用了。所以scope选择provided。
xml
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
从今往后,只需要在对应的类上加上这几个注解,就能完成对应的编译工作
- @AllArgsConstructor:生成全参构造器。
- @NoArgsConstructor:生成无参构造器。
- @Getter/@Setter: 作用类上,生成所有成员变量的getter/setter方法;作用于成员变量上,生成该成员变量的getter/setter方法。可以设定访问权限及是否懒加载等。
- @Data:作用于类上,是以下注解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
- @Log:作用于类上,生成日志变量。针对不同的日志实现产品,有不同的注解。
注解还有很多,自行学习。
less
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final Long serialVersionUID = 1L;
private int id;
private String username;
private String password;
}