MyBatis 源码分析 - MyBatis入门

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

INSERT INTO author (id, name, age, sex, email)

VALUES

(1,‘coolblog.xyz’,28,0,‘coolblog.xyz@outlook.com’),

(2,‘nullllun’,29,1,‘coolblog.xyz@outlook.com’);

/*!40000 ALTER TABLE author ENABLE KEYS */;

UNLOCK TABLES;

Dump of table student

------------------------------------------------------------

DROP TABLE IF EXISTS student;

CREATE TABLE student (

id int(11) unsigned NOT NULL AUTO_INCREMENT,

name varchar(32) DEFAULT NULL,

age tinyint(4) DEFAULT NULL,

PRIMARY KEY (id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

LOCK TABLES student WRITE;

/*!40000 ALTER TABLE student DISABLE KEYS */;

INSERT INTO student (id, name, age)

VALUES

(1,‘coolblog’,20);

/*!40000 ALTER TABLE student ENABLE KEYS */;

UNLOCK TABLES;

3.1 使用 MyBatis 访问数据库

前面说过,MyBatis 是一种半自动化的 Java 持久化框架,使用 MyBatis 需要用户自行维护 SQL。这里,我们把 SQL 放在 XML 中,文件名称为 ArticleMapper.xml。相关配置如下:

SELECT

id, title, author, content, create_time

FROM

article

WHERE

author = #{author} AND create_time > #{createTime}

上面的 SQL 用于从article表中查询出某个作者从某个时候到现在所写的文章记录。在 MyBatis 中,SQL 映射文件需要与数据访问接口对应起来,比如上面的配置对应xyz.coolblog.dao.ArticleDao接口,这个接口的定义如下:

public interface ArticleDao {

List

findByAuthorAndCreateTime(@Param(“author”) String author, @Param(“createTime”) String createTime);

}

要想让 MyBatis 跑起来,还需要进行一些配置。比如配置数据源、配置 SQL 映射文件的位置信息等。本节所使用到的配置如下:

到此,MyBatis 所需的环境就配置好了。接下来把 MyBatis 跑起来吧,相关测试代码如下:

public class MyBatisTest {

private SqlSessionFactory sqlSessionFactory;

@Before

public void prepare() throws IOException {

String resource = “mybatis-config.xml”;

InputStream inputStream = Resources.getResourceAsStream(resource);

sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

inputStream.close();

}

@Test

public void testMyBatis() throws IOException {

SqlSession session = sqlSessionFactory.openSession();

try {

ArticleDao articleDao = session.getMapper(ArticleDao.class);

List

articles = articleDao.findByAuthorAndCreateTime(“coolblog.xyz”, “2018-06-10”);

} finally {

session.commit();

session.close();

}

}

}

在上面的测试代码中,prepare 方法用于创建SqlSessionFactory工厂,该工厂的用途是创建SqlSession。通过 SqlSession,可为我们的数据库访问接口ArticleDao接口生成一个代理对象。MyBatis 会将接口方法findByAuthorAndCreateTime和 SQL 映射文件中配置的 SQL 关联起来,这样调用该方法等同于执行相关的 SQL。

上面的测试代码运行结果如下:

img

如上,大家在学习 MyBatis 框架时,可以配置一下 MyBatis 的日志,这样可把 MyBatis 的调试信息打印出来,方便观察 SQL 的执行过程。在上面的结果中,==>符号所在的行表示向数据库中输入的 SQL 及相关参数。<==符号所在的行则是表示 SQL 的执行结果。

3.2 JDBC 和 Spring JDBC 简介

JDBC

JDBC 作为 Java 平台的数据库访问规范,它仅提供一种访问数据库的能力。使用步骤:加载数据库驱动,创建数据库连接对象,创建 SQL 执行语句对象,执行 SQL 和处理结果集。缺点: JDBC 流程繁琐;拼接 SQL 可能会导致 SQL 出错;将 SQL 和 Java 代码混在一起,会降低代码的可读性,不利于维护;执行结果的处理麻烦;用户还需要手动管理数据库连接,开始要手动获取数据库连接。使用好后,又要手动关闭数据库连接

Spring JDBC

Spring JDBC 在 JDBC 基础上,进行了比较薄的包装,易用性得到了不少提升。不过它也是存在一定缺陷的,比如 SQL 仍是写在代码中,需要用户自行处理 ResultSet 等。不过与 JDBC 相比,使用 Spring JDBC 无需手动加载数据库驱动,获取数据库连接,以及创建 Statement 对象等操作。总的来说,易用性上得到了不少的提升。

3.3 MyBatis 和 Hibernate 比较

MyBatis 和 Hibernate共同点:都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。

| | MyBatis | Hibernate |

| — | — | — |

| 映射关系 | 配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单 | 配置Java对象与数据库表的对应关系,多表关联关系配置复杂 |

| SQL优化和移植性 | MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。 | Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。 |

| 学习成本 | MyBatis 是轻量级框架,学习使用门槛低 | Hibernate 是重量级框架,学习使用门槛高 |

| 使用场景 | 适合于需求变化频繁,大型的项目,比如:互联网电子商务系统 | 适合于需求相对稳定,中小型的项目,比如:办公自动化系统 |

| 总结 | MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架 | Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架 |

4.如何使用 MyBatis


使用 MyBatis 的方式主要有:单独使用 MyBatis,与 Spring 整合使用,与 Spring Boot 整合使用。鉴于目前使用 Spring Boot 的方式比较流行,接下来就介绍 MyBatis 与 Spring Boot 整合使用,其他两种方式读者感兴趣可以自行进行尝试。

4.1 在pom.xml添加依赖

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.4

mysql

mysql-connector-java

runtime

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-validation

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-test

test

4.2 在application.yml配置

应用服务 WEB 访问端口

server:

port: 8080

spring配置

spring:

application:

name: spring-boot-mybatis

数据库配置

datasource:

type: com.zaxxer.hikari.HikariDataSource

url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false&tinyInt1isBit=false&serverTimezone=GMT%2B8

driver-class-name: com.mysql.cj.jdbc.Driver

username: root

password: root

mybatis配置

mybatis:

给实体类配置别名

type-aliases-package: com.jourwon.spring.boot.*.entity

加载mybatis核心配置文件

configuration 和 configLocation 不能同时存在

config-location: classpath:mybatis/mybatis-config.xml

mapper-locations: classpath:mybatis/mapper/**/*Mapper.xml

configuration:

开发环境控制台打印sql语句

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

开启驼峰规则自动映射字段属性值:如字段为user_name的可以映射到userName属性中

map-underscore-to-camel-case: true

设置sql执行超时时间,以秒为单位的全局sql超时时间设置,当超出了设置的超时时间时,会抛出SQLTimeoutException

default-statement-timeout: 30

解决查询返回结果含null没有对应字段值问题

call-setters-on-nulls: true

4.3 mapper文件

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

user_id, username, password, mobile_phone_number, email, delete_state, create_time,

update_time

select

from user

where user_id = #{userId}

4.4 创建用户表与添加用户数据

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;


– Table structure for user


DROP TABLE IF EXISTS user;

CREATE TABLE user (

user_id bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT ‘用户id’,

username varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT ‘’ COMMENT ‘用户名’,

password varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT ‘’ COMMENT ‘密码’,

mobile_phone_number char(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT ‘’ COMMENT ‘手机号码’,

email varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT ‘’ COMMENT ‘邮箱’,

delete_state tinyint UNSIGNED NULL DEFAULT 0 COMMENT ‘用户状态,0表示未删除,1表示删除’,

create_time datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,

update_time datetime NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT ‘更新时间’,

PRIMARY KEY (user_id) USING BTREE,

UNIQUE INDEX uk_username(username) USING BTREE COMMENT ‘用户名唯一’

) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘用户表’ ROW_FORMAT = COMPACT;


– Records of user


INSERT INTO user VALUES (1, ‘JourWon’, ‘123456’, ‘13800000000’, ‘JourWon@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (2, ‘马云’, ‘123456’, ‘13800000011’, ‘JackMa@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (3, ‘马化腾’, ‘123456’, ‘13800000022’, ‘PonyMa@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (4, ‘李彦宏’, ‘123456’, ‘13800000033’, ‘RobinLee@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (5, ‘任正非’, ‘123456’, ‘13800000044’, ‘RenZhengfei@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (6, ‘Jobs’, ‘123456’, ‘13800000055’, ‘Jobs@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (7, ‘Bill Gates’, ‘123456’, ‘13800000066’, ‘Bill Gates@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

INSERT INTO user VALUES (8, ‘Buffett’, ‘123456’, ‘13800000077’, ‘Buffett@163.com’, 0, ‘2021-01-31 20:54:01’, NULL);

SET FOREIGN_KEY_CHECKS = 1;

4.5 创建实体类

User

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

@ApiModel(value = “User-用户”)

public class User implements Serializable {

private static final long serialVersionUID = 5949235389416637695L;

@ApiModelProperty(value = “用户id”)

private Long userId;

@ApiModelProperty(value = “用户名”)

private String username;

@ApiModelProperty(value = “密码”)

private String password;

@ApiModelProperty(value = “手机号码”)

private String mobilePhoneNumber;

@ApiModelProperty(value = “邮箱”)

private String email;

@ApiModelProperty(value = “删除状态(0:未删除,1:已删除)”)

private Short deleteState;

@ApiModelProperty(value = “创建时间”)

private LocalDateTime createTime;

@ApiModelProperty(value = “更新时间”)

private LocalDateTime updateTime;

}

4.6 新建dto和vo对象

UserDTO

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

@ApiModel(value = “UserDTO-用户”)

public class UserDTO implements Serializable {

private static final long serialVersionUID = -3869159805013367683L;

@ApiModelProperty(value = “用户id”)

private Long userId;

@ApiModelProperty(value = “用户名”)

private String username;

@ApiModelProperty(value = “手机号码”)

private String mobilePhoneNumber;

@ApiModelProperty(value = “邮箱”)

private String email;

@ApiModelProperty(value = “删除状态(0:未删除,1:已删除)”)

private Short deleteState;

@ApiModelProperty(value = “创建时间”)

private LocalDateTime createTime;

@ApiModelProperty(value = “更新时间”)

private LocalDateTime updateTime;

}

UserVO

@Data

@Builder

@NoArgsConstructor

@AllArgsConstructor

@ApiModel(value = “UserVO-用户”)

public class UserVO implements Serializable {

private static final long serialVersionUID = -2490262010558991748L;

@ApiModelProperty(value = “用户id”)

private Long userId;

@ApiModelProperty(value = “用户名”)

private String username;

@ApiModelProperty(value = “手机号码”)

private String mobilePhoneNumber;

@ApiModelProperty(value = “邮箱”)

private String email;

@ApiModelProperty(value = “删除状态(0:未删除,1:已删除)”)

private Short deleteState;

@ApiModelProperty(value = “创建时间”)

private LocalDateTime createTime;

@ApiModelProperty(value = “更新时间”)

private LocalDateTime updateTime;

}

4.7 bean转换工具类

public class BeanTransformUtils {

public static T transform(Object source, Class targetClass) {

Assert.notNull(source, “Source must not be null”);

Assert.notNull(targetClass, “Target class must not be null”);

T targetObj = null;

try {

targetObj = targetClass.newInstance();

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

assert targetObj != null;

BeanUtils.copyProperties(source, targetObj);

return targetObj;

}

}

4.8 用户service接口

public interface UserService {

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

image

上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

image

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
Utils {

public static T transform(Object source, Class targetClass) {

Assert.notNull(source, “Source must not be null”);

Assert.notNull(targetClass, “Target class must not be null”);

T targetObj = null;

try {

targetObj = targetClass.newInstance();

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

assert targetObj != null;

BeanUtils.copyProperties(source, targetObj);

return targetObj;

}

}

4.8 用户service接口

public interface UserService {

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

[外链图片转存中…(img-R6rmiKOO-1714706693471)]

上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

[外链图片转存中…(img-U75vKwpq-1714706693472)]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值