最新Mybatis快速上手(详解)
Posted Mest514
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最新Mybatis快速上手(详解)相关的知识,希望对你有一定的参考价值。
前言
Mybatis快速学习,最全最详细,入坑狂神,ssm框架必备资源,文档笔记来源:kuangshenstudy,结合视频资源食用更佳,相关资源在文末,有需要自取。
一、Mybatis简介?
MyBatis 本是 Apache 的一个开源项目 iBatis ,2010年这个项目由 Apache Software Foundation 迁移到了 Google Code ,并且改名为 MyBatis。 MyBatis 是一个基于 Java 的持久层框架。 MyBatis 提供的持久层框架包括 sQL Maps 和 Data Access Objects ( DAO ),它消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。 MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs ( Plain Old Java Objects ,普通的 Java 对象)映射成数据库中的记录。
目前, Java 的持久层框架产品有许多,常见的有 Hibernate 和 MyBatis 。 MyBatis 是一个半自动映射的框架,因为 MyBatis 需要手动匹配PoJ0、 sQL 和映射关系;而 Hibernate 是一个全表映射的框架,只需提供POJ0和映射关系即可。 MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架; Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。两个持久层框架各有优缺点,开发者应根据实际应用选择它们。
二、Mybatis的工作原理
- 读取Mybatis配置文件:(例如数据库连接信息)
- 加载映射文件:(即sql映射文件,该文件中配置了操作数据库的sql语句,mybatis-config.xml文件可以加载多个映射文件,每个文件对应数据库中的一张表)
- 构造会话工厂:(通过Mybatis的环境配置信息构造会话工厂SqlSessionFactory)
- 创建会话对象:由会话对象创建SqlSession对象,该对象中包含了执行sql语句的所有方法。
- Executor执行器: MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 sql 语句,同时负责查询缓存的维护。
- MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 sql 语句的 id 、参数等信息。
- 输入参数映射:输入参数类型可以是 Map 、 List 等集合类型,也可以是基本数据类型和pojo类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
- 输出结果映射:输出结果类型可以是 Map 、 List 等集合类型,也可以是基本数据类型和pojo类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
mybatis框架的执行流程图:
MyBatis的优点
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件就可以了,易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
- 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
- 提供xml标签,支持编写动态sql
- 最重要的一点,使用的人多!公司需要!
三、MyBatis第一个程序
思路流程:搭建环境–>导入Mybatis—>编写代码—>测试
1、搭建实验数据库
2、导入MyBatis相关 jar 包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
3、编写MyBatis核心配置文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/mest/dao/userMapper.xml"/>
</mappers>
</configuration>
4、编写MyBatis工具类
package com.mest.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.IOException;
import java.io.InputStream;
//工具类
public class MybatisUtils
private static SqlSessionFactory sqlSessionFactory;
static
try
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
catch (IOException e)
e.printStackTrace();
public static SqlSession getSqlSession()
return sqlSessionFactory.openSession();
5、创建实体类
public class User
private int id; //id
private String name; //姓名
private String pwd; //密码
//构造,有参,无参
//set/get
//toString()
//可用注解
6、编写Mapper接口类
import com.kuang.pojo.User;
import java.util.List;
public interface UserMapper
List<User> selectUser();
7、编写Mapper.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.kuang.dao.UserMapper">
<select id="selectUser" resultType="com.mest.pojo.User">
select * from user
</select>
</mapper>
注意:namespace的路径不可出错
8、编写测试类
public class MyTest
@Test
public void selectUser()
SqlSession session = MybatisUtils.getSession();
//方法一:
//List<User> users = session.selectList("com.kuang.mapper.UserMapper.selectUser");
//方法二:
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUser();
for (User user: users)
System.out.println(user);
session.close();
Maven静态资源过滤问题:在pom.xml中导入
<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>
9、运行测试
成功,所有user信息被打印
四、CURD操作
基于上例,进阶CURD操作
将上面案例中的UserMapper接口改名为 UserDao;
将UserMapper.xml中的namespace改为为UserDao的路径 ;
再次测试.
结论:
配置文件中namespace中的名称为对应Mapper接口或者Dao接口的完整包名,必须一致!
1、select
- select标签是mybatis中最常用的标签之一
- select语句有很多属性可以详细配置每一条SQL语句
- SQL语句返回值类型。【完整的类名或者别名】
- 传入SQL语句的参数类型 。【万能的Map,可以多尝试使用】
- 命名空间中唯一的标识符
- 接口中的方法名与映射文件中的SQL语句ID 一一对应
- id
- parameterType
- resultType
需求:根据id查询用户
1、在UserMapper中添加对应方法
public interface UserMapper
//获取查询全部用户
List<User> getuerlist();
//根据id查询用户
User getUserById(int id);
2、在UserMapper.xml中添加Select语句
<select id="getUserById" parameterType="int" resultType="com.mest.pojo.User">
select * from mybatis.user where id=#id
</select>
3、测试类中测试
@Test
public void getUserById()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
User userById = mapper.getUserById(2);
System.out.println(userById);
sqlSession.close();
1.1万能查询Map和传参查询
思路一:使用万能的Map
1、在接口方法中,参数直接传递Map;
//万能map
Integer addUser2(Map<String,Object> map);
2、编写sql语句的时候,需要传递参数类型,参数类型为map
<select id="getUserById2" parameterType="map" resultType="com.mest.pojo.User">
select * from mybatis.user where id=#id and name=#name
</select>
3、在使用方法的时候,Map的 key 为 sql中取的值即可,没有顺序要求!
@Test
public void getUserById2()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Map<String,Object> map=new HashMap<String, Object>();
System.out.println(map.get(2));
sqlSession.close();
思路二:直接在方法中传递参数
1、在接口方法的参数前加 @Param属性
2、Sql语句编写的时候,直接取@Param中设置的值即可,不需要单独设置参数类型
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);
/*
<select id="selectUserByNP" resultType="com.kuang.pojo.User">
select * from user where name = #username and pwd = #pwd
</select>
*/
1.2思考:模糊查询
//模糊查询用户
List<User> getUserLike(String value);
<select id="getUserLike" resultType="com.mest.pojo.User">
select * from mybatis.user where name like #value ;
</select>
@Test
public void getUserLike()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserLike("%西%");
for (User user : userList)
System.out.println(user);
sqlSession.close();
2、insert
需求:给数据库增加一个用户
1、在UserMapper接口中添加对应的方法
//insert用户
Integer addUser(User user);
2、在UserMapper.xml中添加insert语句
<insert id="addUser" parameterType="com.mest.pojo.User">
insert into mybatis.user (id,name,pwd) values($id,#name,#pwd);
</insert>
3、测试
@Test
public void addUser()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int res = mapper.addUser(new User(10, "fake", "123456"));
if(res>0)
System.out.println("添加成功");
//提交事物
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
3、update
需求:修改用户的信息
1、同理,编写接口方法
//update
Integer upDateUser(User user);
2、编写对应的配置文件SQL
<update id="upDateUser" parameterType="com.mest.pojo.User">
update mybatis.user set name=#name,pwd=#pwd where id=#id;
</update>
3、测试
@Test
public void upDateUser()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Integer res = mapper.upDateUser(new User(4, "赛赛", "520"));
if(res>0)
System.out.println("修改成功");
//提交事物
sqlSession.commit();//提交事务,重点!不写的话不会提交到数据库
//关闭sqlSession
sqlSession.close();
4、delete
需求:根据id删除一个用户
1、同理,编写接口方法
//delete
Integer deleteUser(int id);
2、编写对应的配置文件SQL
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#id;
</delete>
3、测试
@Test
public void deleteUser()
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
Integer res = mapper.deleteUser(1);
if(res>0)
System.out.println("删除成功");
//提交事物
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
5、配置解析
5.1 核心配置文件
- mybatis-config.xml 系统核心配置文件
- MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。
- 能配置的内容如下:
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
5.2 environments元素
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
- 配置MyBatis的多套运行环境,将SQL映射到多个不同的数据库上,必须指定其中一个为默认运行环境(通过default指定)
- 子元素节点:environment
-
dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
-
数据源是必须配置的。
-
有三种内建的数据源类型
type="[UNPOOLED|POOLED|JNDI]")
-
unpooled:这个数据源的实现只是每次被请求时打开和关闭连接。
-
pooled:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来 , 这是一种使得并发 Web
应用快速响应请求的流行处理方式。 -
jndi:这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI
上下文的引用。 -
数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等…
-
详情:点击查看官方文档
-
这两种事务管理器类型都不需要设置任何属性。
-
具体的一套环境,通过设置id进行区别,id保证唯一!
-
子元素节点:transactionManager - [ 事务管理器 ]
-
子元素节点:数据源(dataSource)
-
5.3 mappers元素
- 映射器 : 定义映射SQL语句文件
- 既然 MyBatis 的行为其他元素已经配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括 file:/// 的URL),或类名和包名等。映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始,还支持接口映射器,这种映射器方式允许以Java代码的方式注解定义SQL语句,非常简洁。
引入资源方式
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的完全限定类名
需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
</mappers>
<!--
将包内的映射器接口实现全部注册为映射器
但是需要配置文件名称和接口名称一致,并且位于同一目录下
-->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
Mapper文件
<?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.kuang.mapper.UserMapper">
</mapper>
namespace中文意思:命名空间,作用如下:
- namespace的命名必须跟某个接口同名
- 接口中的方法与映射文件中sql语句id应该一一对应
- namespace和子元素的id联合保证唯一 , 区别不同的mapper
- 绑定DAO接口
- namespace命名规则 : 包名+类名
5.4 Properties优化
数据库这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。具体的官方文档
我们来优化我们的配置文件
第一步 ; 在资源目录下新建一个db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8
username=root
password=123456
第二步 : 将文件导入properties 配置文件
<configuration>
<!--导入properties文件-->
<properties resource="db.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"MyBatis-Plus 是一个 MyBatis 的增强工具;
先构建一个 spring boot 项目
1. 添加依赖
<!-- 数据库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<!-- 代码生成器 如不使用可以不加 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency>
<!-- Druid连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<!-- 模板引擎 和代码生成器搭配使用,如不使用可以不加 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
2.配置
如果是 .yml 文件 ↓
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 数据源类型
url: jdbc:h2:mem:test
username: root
password: test
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
如果是 .properties文件 ↓
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.url = jdbc:h2:mem:test
spring.datasource.username = root
spring.datasource.password = test
mybatis-plus.configuration.log-impl= org.apache.ibatis.logging.stdout.StdOutImpl #日志
更多 dataSource 配置 :https://www.cnblogs.com/toughzcf/p/9835867.html
在 Spring Boot 启动类中添加 @MapperScan
注解,扫描 Mapper 文件夹:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {"com.example.*"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3. 生成 @Data,mapper 文件(此处我是用代码生成器直接生成的)
代码生成器代码↓
// 代码生成器
@Test
void generator() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
globalConfig.setAuthor("author"); // 作者名
globalConfig.setOpen(false);
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl(jdbcUrl); // 数据库连接地址
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
dataSourceConfig.setUsername("root"); // 数据库用户名
dataSourceConfig.setPassword("3wHNY2Bq"); // 数据库密码
//3、策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setCapitalMode(true) // 开启全局大写命名
// .setDbColumnUnderline(true) // 表名字段名使用下划线
.setNaming(NamingStrategy.underline_to_camel)//下划线转驼峰的命名方式
.setTablePrefix("xxxx_") // 表名前缀
.setEntityLombokModel(true) // 使用lombok
.setInclude("xxxx_sms"); // 逆向工程使用的表
//4、包名策略配置
PackageConfig packageConfig = new PackageConfig();
packageConfig
.setParent("com.example.demo") // 设置包名的parent
.setMapper("dao.xxxx")
// .setService("service") // service 文件目录
// .setController("controller") // controller 文件目录
.setEntity("entity.xxxx") // data文件目录
.setXml("mapper/xxxx"); // 设置xml文件的目录 (暂没有找到xml文件直接存到 resource 目录下的方法,由于resource目录和java目录同级)
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
//控制 不生成 controller,server,impl 文件
templateConfig.setController("").setService("").setServiceImpl("");
AutoGenerator autoGenerator = new AutoGenerator();
autoGenerator.setGlobalConfig(globalConfig)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(packageConfig)
.setTemplate(templateConfig);
//6、执行
autoGenerator.execute();
}
4. 现在就可以直接使用增删改查了
@Service
public class HomeImpl implements HomeService {
@Autowired
private SmsMapper smsMapper;
@Override
public List sms(String phone) {
QueryWrapper<Sms> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", phone);
return smsMapper.selectList(queryWrapper);
}
}