一、Mybatis简述
1.含义
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
2.架构
3.执行过程
(1)首先Mybaitis自己的一个Resources类会去调用一个叫getResourceAsStream()的方法加载配置MyBatis的核心配置文件,得到一个流对象。(本质上还是走的java.lang包下的ClassLoader类加载器的getResourceAsStream)
(2)有了这个流对象,下面执行这个方法会先去创建一个SqlSessionFactoryBuilder对象(构建者对象),调用build()方法,传入第一步我们得到的那个流对象。在这个过程中,首先,MyBatis会先去创建一个XMLConfigBuilder解析器对象,解析我们刚才传进来的那个流对象解析完成之后,返回一个configuration对象,这个对象里面封装了解析之后我们配置的信息正好这个configuration对象,就是我们这个方法创建(I)SqlSessionFactory类型对象需要的参数返回的就是一个实现了SqlSessionFactory接口的DefaultSqlSessionFactory对象
(3)有了这个SqlSesionFactory实现类的对象之后,我们调用openSession()的方法,这个过程中需 要 通 过TransactionFactory 生成 Transaction 对象, 并且, 还需要创建核心执行器 Executor 对象,基于这些条件,最终创建了实现SqlSession接口的DefaultSqlSession对象
(4)之后, 通过 SqlSession 对象执行相应的操作, 如果执行成功, 调用 commit 方法提交事务; 如果失败, 调用rollback 方法事务回滚. 最后, 调用 close 方法关闭session 资源.
4.应用(实例)
(1)新建项目
注:可能会出现一下错误
解决方案参考
https://www.cnblogs.com/song77/p/12396880.html
(2)选择项目依赖
(3)配置项目
在pom.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>databasedemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>databasedemo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(4)application.properties配置
server.port=8080
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=xyp20000921
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
(5)数据库建表
(6)包类代码
①项目src-main-java-com下分别创建包:controller、entity、mapper、service,用来实现控制层、实体层、映射层、业务层
②src-main-resources下创建mapper包用于存放*Mapper.xml文件
③创建entity实体类Student
package com.example.databasedemo.entity;
public class Student {
private int no;
private String name;
private int age;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + ''' +
", age='" + age + ''' +
'}';
}
}
④创建Mapper映射操作StudentMapper类:
package com.example.databasedemo.mapper;
import com.example.databasedemo.entity.Student;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface StudentMapper {
public List<Student> findAllStudent();
List<Student> findStudentByno(int no);
}
<?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">
<mapper namespace="com.example.databasedemo.mapper.StudentMapper">
<resultMap id="result" type="com.example.databasedemo.entity.Student">
<result column="no" jdbcType="INTEGER" property="no" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="age" jdbcType="INTEGER" property="age" />
</resultMap>
<select id="findAllStudent" resultType="com.example.databasedemo.entity.Student">
select * from student;
</select>
<select id="findStudentByno" resultType="com.example.databasedemo.entity.Student">
select * from student where no=#{no};
</select>
</mapper
⑤创建service业务StudentService类
package com.example.databasedemo.service;
import com.example.databasedemo.entity.Student;
import com.example.databasedemo.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService {
@Autowired(required = false)
public StudentMapper studentMapper;
public List<Student> findAllStudent() {
return studentMapper.findAllStudent();
}
public List<Student> findStudentByno(int no) {
return studentMapper.findStudentByno(no);
}
}
⑥创建 controller控制层UserController类
package com.example.databasedemo.controller;
import com.example.databasedemo.entity.Student;
import com.example.databasedemo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/Student")
class UserController {
@Autowired
private StudentService studentService;
@RequestMapping("/getAllStudent")
public List<Student> findAll(){
return studentService.findAllStudent();
}
@RequestMapping("/getStudentByno/{no}")
public List<Student> findUserByStudentId(@PathVariable int no){
return studentService.findStudentByno(no);
}
}
⑦运行测试
http://localhost:8080/Student/getAllStudent/
http://localhost:8080/Student/getStudentByno/2
二、JDBC简述
1.含义
Java数据库连接,(Java D
atabase Connect
ivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
2.程序类型
类型1
JDBC-ODBC桥这种类型的驱动把所有JDBC的调用传递给ODBC,再让后者调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如Oracle中的oci.dll)。
类型2
本地API驱动这种类型的驱动通过客户端加载数据库厂商提供的本地代码库(C/C++等)来访问数据库,而在驱动程序中则包含了Java代码。
类型3
网络协议驱动这种类型的驱动给客户端提供了一个网络API,客户端上的JDBC驱动程序使用套接字(Socket)来调用服务器上的中间件程序,后者在将其请求转化为所需的具体API调用。
类型4
本地协议驱动这种类型的驱动使用Socket,直接在客户端和数据库间通信。
3.建立连接
①加载(注册)数据库
你需要做的第一事情是你与想要使用的 DBMS 建立一个连接。这包含 2 个步骤:装载驱动程序并建立连接。装载驱动程序装载驱动程序只需要非常简单的一行代码。例如,你想要使用 JDBC-ODBC 桥驱动程序,可以用下列代码装载它:Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver”);你的驱动程序文档将告诉你应该使用的类名。例如, 如果类名是 jdbc.DriverXYZ ,你将用代码以下的代码装载驱动程序:Class.forName(“jdbc.DriverXYZ”);你不需要创建一个驱动程序类的实例并且用 DriverManager 登记它,因为调用 Class.forName 将自动将加载驱动程序类。如果你曾自己创建实例,你将创建一个不必要的副本,但它不会带来什么坏处。加载 Driver 类后,它们即可用来与数据库建立连接。
② 建立连接
第二步就是用适当的驱动程序类与 DBMS 建立一个连接。下列代码是一般的做法:Connection con = DriverManager.getConnection(url,“myLogin”,“myPassword”);这个步骤也非常简单,最难的是怎么提供 url。如果你正在使用 JDBC-ODBC 桥, JDBC URL 将以 jdbc:odbc 开始:余下 URL 通常是你的数据源名字或数据库系统。因此,假设你正在使用 ODBC 存取一个叫 “Fred” 的 ODBC 数据源,你的 JDBC URL 是 jdbc:odbc:Fred。把 “myLogin” 及 “myPassword” 替换为你登陆 DBMS 的用户名及口令。如果你登陆数据库系统的用户名为 “Fernanda” 口令为 “J8”,只需下面的 2 行代码就可以建立一个连接:String url = “jdbc:odbc:Fred”;Connection con = DriverManager.getConnection(url,“Fernanda”,“J8”);如果你使用的是第三方开发了的 JDBC驱动程序,文档将告诉你该使用什么 subprotocol, 就是在 JDBC URL 中放在 jdbc 后面的部分。例如,如果驱动程序开发者注册了 acme 作为 subprotocol, JDBC URL 的第一和第二部分将是 jdbc:acme。驱动程序文档也会告诉你余下 JDBC URL 的格式。JDBC URL 最后一部分提供了定位数据库的信息。如果你装载的驱动程序识别了提供给 DriverManager.getConnection 的 JDBC URL ,那个驱动程序将根据 JDBC URL 建立一个到指定 DBMS 的连接。正如名称所示,DriverManager 类在幕后为你管理建立连接的所有细节。除非你是正在写驱动程序,你可能无需使用此类的其它任何方法,一般程序员需要在此类中直接使用的唯一方法是 DriverManager.getConnection。DriverManager.getConnection 方法返回一个打开的连接,你可以使用此连接创建 JDBC statements 并发送 SQL 语句到数据库。在前面的例子里,con 对象是一个打开的连接,并且我们要在以后的例子里使用它。
③执行SQL语句
④处理结果集
⑤关闭数据库
3.JDBC操作数据库(实例)
(1)数据库建表(同上)
创建学生表
create table student(
no int primary key auto_increment,
name varchar(40),
age int
)character set utf8 collate utf8_general_ci;
插入数据
insert into student(no,name,age) values('1','张三','18');
insert into student(no,name,age) values('2','李四','21');
insert into student(no,name,age) values('3','王二','22');
insert into student(no,name,age) values('4','张飞','42');
insert into student(no,name,age) values('5','小米','74');
(2)IDEA新建项目(同上)
然后在src中新建DatebaseLink类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DatebaseLink {
// MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
//static final String driverName="org.gjt.mm.mysql.Driver";
//static final String dbUrl="jdbc:mysql://localhost:3306/test";
// MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
static final String userName="root";
static final String password="lxl060908";
public static void main(String[] args) {
// TODO Auto-generated method stub
Connection conn = null;
Statement stmt = null;
try{
// 注册 JDBC 驱动
Class.forName(JDBC_DRIVER);
// 打开链接
System.out.println("连接数据库...");
conn = DriverManager.getConnection(DB_URL,userName,password);
// 执行查询
System.out.println(" 实例化Statement对象...");
stmt = (Statement) conn.createStatement();
String sql;
sql = "SELECT id, name, password, email FROM users";
ResultSet rs = stmt.executeQuery(sql);
// 展开结果集数据库
while(rs.next()){
// 通过字段检索
int id = rs.getInt("id");
String name = rs.getString("name");
String password = rs.getString("password");
String email = rs.getString("email");
// 输出数据
System.out.print("ID: " + id);
System.out.print(", 姓名: " + name);
System.out.print(", 密码: " +password);
System.out.print(", 邮箱: " +email);
System.out.print("\n");
}
// 完成后关闭
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
// 处理 JDBC 错误
se.printStackTrace();
}catch(Exception e){
// 处理 Class.forName 错误
e.printStackTrace();
}finally{
// 关闭资源
try{
if(stmt!=null) stmt.close();
}catch(SQLException se2){
}// 什么都不做
try{
if(conn!=null) conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
System.out.println("Goodbye!");
}
}
(3)导入JDBC的jar包
(4)运行测试
三、从JDBC到Mybatis的改进
1.数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能
解决问题:
数据库连接的获取和关闭我们可以使用数据库连接池来解决资源浪费的问题。通过连接池就可以反复利
用已经建立的连接去访问数据库了。减少连接的开启和关闭的时间。
2.Sql语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代
码。
解决问题:
Mybatis将SQL语句写在配置文件中通过xml或注解的方式将要执行的各种statement(statement、
preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生
成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。这样当需要更改
SQL时,只需要更改配置文件。(不影响接口的情况下)
3.使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也
可能少,修改sql还要修改代码,系统不易维护。
解决问题:
同上,配置文件。
4.对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记
录封装成pojo对象解析比较方便。
解决问题:
Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过
Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对
结果的解析处理过程。
四、总结
参考连接
https://blog.youkuaiyun.com/m0_52869979/article/details/120861060
https://blog.youkuaiyun.com/weixin_56102526/article/details/120825699