共计 9931 个字符,预计需要花费 25 分钟才能阅读完成。
关注“Java 后端技术全栈”**
回复“面试”获取全套大厂面试材料
前言
后面咱们讲过 Spring Boot 集成 JPA,然而因为很多小伙伴的我的项目中用的并不是 JPA,用的是 Mybatis,并且我也考察过很多敌人,三个 ORM 框架应用比例大抵为
Mybatis:JPA:Hibernate: 其余 =6:3:0.5:0.5
不承受反驳,因为没有多大意义。
面试题:Mybatis 和 Hibernate 的区别
这题目答案网上多得很,能够用漫天非来形容。然而咱们这里会关注一个点不同点:sql 的优化。
因为 mybatis 的 sql 都是写在 xml 里,因而优化 sql 比 hibernate 不便很多。而 hibernate 的 sql 很多都是主动生成的,无奈间接保护 sql;虽有 hql,但性能还是不迭 sql 弱小,见到报表等变态需要时,hql 也歇菜,也就是说 hql 是有局限的;hibernate 尽管也反对原生 sql,但开发模式上却与 orm 不同,须要转换思维,因而应用上不是十分不便。总之写 sql 的灵便度上 hibernate 不迭 mybatis。其实在 Mybatis 中咱们也能够应用注解的形式来操作数据库(注解中写 sql)。
xml 形式集成
MyBatis 是现如今最风行的 ORM 框架之一,咱们先来理解一下什么是 ORM 框架。
ORM 框架
对象关系映射(Object Relational Mapping,ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的景象的技术。简略的说,ORM 是通过应用形容对象和数据库之间映射的元数据,将程序中的对象主动长久化到关系数据库中。
为什么须要 ORM?
当你开发一个应用程序的时候(不应用 O/R Mapping),可能会写不少数据拜访层代码,用来从数据库保留、删除、读取对象信息等;在 DAL 中写了很多的办法来读取对象数据、扭转状态对象等工作,而这些代码写起来总是反复的。针对这些问题 ORM 提供了解决方案,简化了将程序中的对象长久化到关系数据库中的操作。
ORM 框架的实质是简化编程中操作数据库的编码,在 Java 畛域倒退到当初基本上就剩两家最为风行,一个是声称能够不必写一句 SQL 的 Hibernate,一个是以动静 SQL 见长的 MyBatis,两者各有特点。在企业级零碎开发中能够依据需要灵便应用,会发现一个乏味的景象:传统企业大都喜爱应用 Hibernate,而互联网行业通常应用 MyBatis。
MyBatis 介绍
MyBatis 是一款规范的 ORM 框架,被宽泛的利用于各企业开发中。MyBatis 最早是 Apache 的一个开源我的项目 iBatis,2010 年这个我的项目由 Apache Software Foundation 迁徙到了 Google Code,并且改名为 MyBatis,2013 年 11 月又迁徙到 Github。从 MyBatis 的迁徙史,也能够看出源码托管平台的发展史,GitHub 目前曾经成为世界上最大的开源软件托管平台,倡议大家多多关注这个寰球最大的同性社交网站。
MyBatis 反对一般的 SQL 查问,存储过程和高级映射的优良长久层框架。MyBatis 打消了简直所有的 JDBC 代码和参数的手工设置以及对后果集的检索封装。MaBatis 能够应用简略的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJO(Plain Old Java Objects,一般的 Java 对象)映射成数据库中的记录。
作为一款应用宽泛的开源软件,它的特点有哪些呢?
长处
- SQL 被对立提取进去,便于对立治理和优
- SQL 和代码解耦,将业务逻辑和数据拜访逻辑拆散,使零碎的设计更清晰、更易保护、更易单元测试
- 提供映射标签,反对对象与数据库的 ORM 字段关系映射
- 提供对象关系映射标签,反对对象关系组件保护
- 灵便书写动静 SQL,反对各种条件来动静生成不同的 SQL
毛病
- 编写 SQL 语句时工作量很大,尤其是字段多、关联表多时,更是如此
- SQL 语句依赖于数据库,导致数据库移植性差
MyBatis 几个重要的概念
Mapper 配置 能够应用基于 XML 的 Mapper 配置文件来实现,也能够应用基于 Java 注解的 MyBatis 注解来实现,甚至能够间接应用 MyBatis 提供的 API 来实现。
Mapper 接口 是指自行定义的一个数据操作接口,相似于通常所说的 DAO 接口。晚期的 Mapper 接口须要自定义去实现,当初 MyBatis 会主动为 Mapper 接口创立动静代理对象。Mapper 接口的办法通常与 Mapper 配置文件中的 select、insert、update、delete 等 XML 结点存在一一对应关系。
Executor,MyBatis 中所有的 Mapper 语句的执行都是通过 Executor 进行的,Executor 是 MyBatis 的一个外围接口。
SqlSession,是 MyBatis 的要害对象,是执行长久化操作的独享,相似于 JDBC 中的 Connection,SqlSession 对象齐全蕴含以数据库为背景的所有执行 SQL 操作的办法,它的底层封装了 JDBC 连贯,能够用 SqlSession 实例来间接执行被映射的 SQL 语句。
SqlSessionFactory,是 MyBatis 的要害对象,它是单个数据库映射关系通过编译后的内存镜像。SqlSessionFactory 对象的实例能够通过 SqlSessionFactoryBuilder 对象类取得,而 SqlSessionFactoryBuilder 则能够从 XML 配置文件或一个事后定制的 Configuration 的实例构建出。
MyBatis 的工作流程如下:
- 首先加载 Mapper 配置的 SQL 映射文件,或者是注解的相干 SQL 内容。
- 创立会话工厂,MyBatis 通过读取配置文件的信息来结构出会话工厂(SqlSessionFactory)。
- 创立会话。依据会话工厂,MyBatis 就能够通过它来创立会话对象(SqlSession),会话对象是一个接口,该接口中蕴含了对数据库操作的增、删、改、查办法。
- 创立执行器。因为会话对象自身不能间接操作数据库,所以它应用了一个叫做数据库执行器(Executor)的接口来帮它执行操作。
- 封装 SQL 对象。在这一步,执行器将待处理的 SQL 信息封装到一个对象中(MappedStatement),该对象包含 SQL 语句、输出参数映射信息(Java 简略类型、HashMap 或 POJO)和输入后果映射信息(Java 简略类型、HashMap 或 POJO)。
- 操作数据库。领有了执行器和 SQL 信息封装对象就应用它们拜访数据库了,最初再返回操作后果,完结流程。
在咱们具体的应用过程中,就是依照上述的流程来执行。
什么是 MyBatis-Spring-Boot-Starter?
mybatis-spring-boot-starter 是 MyBatis 帮忙咱们疾速集成 Spring Boot 提供的一个组件包,应用这个组件能够做到以下几点:
- 构建独立的利用
- 简直能够零配置
- 须要很少的 XML 配置
mybatis-spring-boot-starter 依赖于 MyBatis-Spring 和 Spring Boot,最新版 1.3.2 须要 MyBatis-Spring 1.3 以上,Spring Boot 版本 1.5 以上。
留神:mybatis-spring-boot-starter 是 MyBatis 官网开发的 Starter,而不是 Spring Boot 官网开发的启动包,其实是 MyBatis 看 Spring Boot 市场应用度十分高,因而被动开发出 Starter 包进行集成,但这一集成的确解决了很多问题,应用起来比以前简略很多。mybatis-spring-boot-starter 次要提供了两种解决方案,一种是简化后的 XML 配置版,一种是应用注解解决所有问题。
MyBatis 以前只有 XML 配置这种应用的模式,到了起初注解应用特地宽泛,MyBatis 也顺应潮流提供了注解的反对,从这里能够看出 MyBatis 始终都跟随着支流技术的变动来欠缺本人。接下来给大家介绍一下如何应用 XML 版本。
XML 版本放弃映射文件的形式,最新版的应用次要体现在不须要实现 Dao 的实现层,零碎会主动依据办法名在映射文件中找到对应的 SQL。
初始化脚本
为了不便我的项目演示,须要在 test 仓库创立 users 表,脚本如下:
CREATE TABLE `users` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 id',
`userName` varchar(32) DEFAULT NULL COMMENT '用户名',
`passWord` varchar(32) DEFAULT NULL COMMENT '明码',
`user_sex` varchar(32) DEFAULT NULL,
`nick_name` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
-- 初始化一条数据
INSERT INTO `my_jpa`.`users`(`id`, `userName`, `passWord`, `user_sex`, `nick_name`) VALUES (1, 'zhangsan', '123456', 'man', 'xiaosan');
增加依赖包
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.4</version>
</dependency>
application.properties 增加配置项
properties
#mysql 配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/my_jpa?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=lwt123456@
#mybatis 配置
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.tian.usercenter.entity
实体类
package com.tian.usercenter.entity;
public class UserEntity {
private Integer id;
private String userName;
private String passWord;
private String userSex;
private String nickName;
//set get
}
在创立一个 UserMapper.java
java
import com.tian.usercenter.entity.UserEntity;
import java.util.List;
public interface UserMapper {List<UserEntity> getAll();
UserEntity getOne(Long id);
void insert(UserEntity user);
void update(UserEntity user);
void delete(Long id);
}
在 resources 目录下增加 mybatis 目录
1. 在该目录下增加 mybatis-config.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>
<settings>
<setting name="callSettersOnNulls" value="true"/>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
<typeAliases>
<typeAlias alias="Integer" type="java.lang.Integer" />
<typeAlias alias="Long" type="java.lang.Long" />
<typeAlias alias="HashMap" type="java.util.HashMap" />
<typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
<typeAlias alias="ArrayList" type="java.util.ArrayList" />
<typeAlias alias="LinkedList" type="java.util.LinkedList" />
</typeAliases>
</configuration>
2. 在本目录下增加 mapper 目录,而后再 mapper 里增加 UserMapper.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" >
<mapper namespace="com.tian.usercenter.dao.UserMapper" >
<resultMap id="BaseResultMap" type="com.tian.usercenter.entity.UserEntity" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="userName" property="userName" jdbcType="VARCHAR" />
<result column="passWord" property="passWord" jdbcType="VARCHAR" />
<result column="user_sex" property="userSex" jdbcType="VARCHAR"/>
<result column="nick_name" property="nickName" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id, userName, passWord, user_sex, nick_name
</sql>
<select id="getAll" resultMap="BaseResultMap" >
SELECT
<include refid="Base_Column_List" />
FROM users
</select>
<select id="getOne" parameterType="java.lang.Integer" resultMap="BaseResultMap" >
SELECT
<include refid="Base_Column_List" />
FROM users
WHERE id = #{id}
</select>
<insert id="insert" parameterType="com.tian.usercenter.entity.UserEntity" >
INSERT INTO users (userName,passWord,user_sex)
VALUES (#{userName}, #{passWord}, #{userSex})
</insert>
<update id="update" parameterType="com.tian.usercenter.entity.UserEntity" >
UPDATE users SET
<if test="userName != null">userName = #{userName},</if>
<if test="passWord != null">passWord = #{passWord},</if>
nick_name = #{nickName}
WHERE id = #{id}
</update>
<delete id="delete" parameterType="java.lang.Integer" >
DELETE FROM users WHERE id =#{id}
</delete>
</mapper>
启动类增加注解
@MapperScan(“com.tian.usercenter.dao”)扫描的 **Mapper.java 目录
@SpringBootApplication
@MapperScan("com.tian.usercenter.dao")
public class UserCenterApplication {public static void main(String[] args) {SpringApplication.run(UserCenterApplication.class, args);
}
}
应用(这里只是为了演示,所以 controller 就间接掉 mapper 了,具体开发中依照我的项目标准来)
@RestController
public class MybatisController {
@Resource
private UserMapper userMapper;
@GetMapping("/mybatis")
public Object mybatis(){List<UserEntity> userEntityList = userMapper.getAll();
return userEntityList;
}
}
启动我的项目,申请地址:http://localhost:8080/mybatis
OK,自此,xml 形式的 Springboot 集成 Mybatis 就搞定了。上面持续搞注解形式:
注解形式集成
application.properties 文件中的配置得删除掉 xml 相干的
#mybatis.config-location=classpath:mybatis/mybatis-config.xml
#mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
mybatis.type-aliases-package=com.tian.usercenter.entity
UserMapper.java 批改
import com.tian.usercenter.entity.UserEntity;
import org.apache.ibatis.annotations.*;
import java.util.List;
public interface UserMapper {@Select("select * from users")
List<UserEntity> getAll();
@Select("select * from users where id= #{id}")
UserEntity getOne(@Param("id") Long id);
@Insert("insert into users (id,userName,passWord,user_sex,nick_name) values (#{id},#{userName}{,#{passWord},#{userSex},#{nickName})")
void insert(UserEntity user);
@Update("update users set username=#{userName} where userName=#{userName}")
void update(UserEntity user);
@Delete("delete from users where id=#{id}")
void delete(@Param("id") Long id);
}
UserMapper.xml 文件删掉。重启我的项目;
申请:http://localhost:8080/mybatis
认真的敌人看到了下面的返回后果中有两个字段 userSex 和 nickName 为 Null。然而在 xml 形式中是失常返回的。
这里能够应用增加一个配置项来解决下换线与驼峰的问题
mybatis.configuration.map-underscore-to-camel-case=true
最初后果为:
好了,下面两种形式都胜利实现,明天就分享到此。
码字不易,心愿你 点个在看 + 分享,谢谢啦!
举荐浏览
扔掉 Postman 吧,试试 Postwoman 高能神器!
Idea 公司真牛逼,发行适宜程序员编程字体