[Study]MyBatis
Posted Spring-_-Bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Study]MyBatis相关的知识,希望对你有一定的参考价值。
文章目录
一、MyBatis 概述及案例
1.1 MyBatis 简介
-
MyBatis
最初是Apache
的一个开源项目iBatis
, 2010 年 6 月 这个项目由Apache Software Foundation
迁移到了Google Code
。随着开发团队转投Google Code
旗下,iBatis3.x
正式更名为MyBatis
。代码于 2013 年 11 月迁移到Github
。iBatis
一词来源于internet
和abatis
的组合,是一个基于Java
的持久层框架。iBatis
提供的持久层框架包括SQL Maps
和Data Access Objects
(DAO) -
MyBatis 的特点
- 支持定制化 SQL、存储过程以及高级映射
- 避免了几乎所有的
JDBC
代码和手动设置参数以及获取结果集 - 使用简单的
XML
或注解用于配置映射,将接口和Java
的POJO
(Plain Old Java Objects
)映射成数据库中的记录 - 一个半自动的
ORM
(Object Relation Mapping
)框架
1.2 持久化技术间的对比
-
JDBC
- SQL 夹杂在 Java 代码中,耦合度高,导致硬编码内伤
- 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
- 代码冗长,开发效率低
-
Hibernate 和 JPA
- 操作简便,开发效率高
- 程序中的长难复杂 SQL 需要绕过框架
- 内部自动生成的 SQL,不容易做特殊优化
- 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难
- 反射操作太多,导致数据库性能下降
-
MyBatis
- 轻量级,性能出色
- SQL 和 Java 编码分开,功能边界清晰。Java 代码专注业务、SQL 语句专注数据
- 开发效率稍逊于 Hibernate,但是完全能够接受
1.3 第一个 MyBatis 程序
-
创建 maven 工程,设置工程打包方式为
jar
包,引入相关依赖<packaging>jar</packaging> <dependencies> <!-- Mybatis 核心 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- junit 测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- mysql 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> </dependencies>
-
resources 目录下创建 MyBatis 的核心配置文件
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> <!-- 设置连接数据库的环境 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="project"/> <property name="password" value="project"/> </dataSource> </environment> </environments> <!-- 引入映射文件 --> <mappers> <mapper resource="mappers/UserMapper.xml"/> </mappers> </configuration>
-
创建 POJO 类
/** * @author Spring-_-Bear * @datetime 6/11/2022 9:24 AM */ public class User private String username; private String password;
-
创建对应 POJO 类的 Mapper,MyBatis中 的
mapper
接口相当于以前的 DAO。区别在于mapper 仅仅是接口,不需要提供实现类(由 MyBatis 提供代理实现类)/** * @author Spring-_-Bear * @datetime 2022/4/13 16:01 */ public interface UserMapper List<User> getAllUsers();
-
在 resources/mapper 目录下创建第 4 步中创建的 Mapper 接口对应的 MyBatis *.xml 映射文件。映射文件的命名规则:对应的接口 + .xml 如 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"> <!-- namespace 需与对应的接口的全类名一致 --> <mapper namespace="edu.whut.bear.mybatis.dao.UserMapper"> <!-- SQL 语句 id 需与接口中对应的方法名一致 --> <!-- List<User> getAllUsers(); --> <select id="getAllUsers" resultType="edu.whut.bear.mybatis.pojo.User"> select * from t_user </select> </mapper>
-
在 MyBatis 的核心配置文件
mybatis-config.xml
引入 UserMapper.xml 文件,如第 2 步中的 20 行 -
测试一把
@Test public void getAllUsers() throws IOException // 读取 MyBatis 核心配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); // 创建 SqlSessionFactoryBuilder 对象以获得 sql 会话工厂对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 获取 sql 会话工厂对象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); // 生产会话,传入参数 true,自动提交事务 SqlSession sqlSession = sqlSessionFactory.openSession(true); // 通过代理模式创建 UserMapper 接口的代理实现类对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 调用方法,执行 sql 语句查询所有用户信息 List<User> allUsers = userMapper.getAllUsers(); allUsers.forEach(System.out::println);
-
项目结构如下
1.4 加入 log4j 日志功能
-
pom.xml 中引入依赖
<!-- log4j 日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
-
resources 目录下新建 log4j 的核心配置文件
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"> <param name="Encoding" value="UTF-8"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %dMM-dd HH:mm:ss,SSS %m (%F:%L) \\n"/> </layout> </appender> <logger name="java.sql"> <!-- 日志级别:FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试) --> <level value="debug"/> </logger> <logger name="org.apache.ibatis"> <level value="info"/> </logger> <root> <level value="debug"/> <appender-ref ref="STDOUT"/> </root> </log4j:configuration>
1.5 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>
<!-- 各标签的配置顺序:
properties?,settings?,typeAliases?,
typeHandlers?,objectFactory?,objectWrapperFactory?,
reflectorFactory?,plugins?,environments?,
databaseIdProvider?,mappers?
-->
<properties resource="jdbc.properties"/>
<typeAliases>
<!-- 自定义 POJO 类别名,不区分大小写,不设置 alias 属性默认值为类名 -->
<!-- <typeAlias type="com.bear.mybatis.pojo.User" alias="User"/> -->
<!-- 以包为单位,为包下的每个类设置默认别名为类名且不区分大小写 -->
<package name="com.bear.mybatis.pojo"/>
</typeAliases>
<!-- 设置连接数据库的环境 -->
<environments default="development">
<environment id="development">
<!-- JDBC:原生 API 进行事务操作管理 || MANAGED:被管理,如 Spring 中的 AOP -->
<transactionManager type="JDBC"/>
<!-- POOLED:使用数据库连接池 || UNPOOLED:不使用数据库连接池 || JNDI:调用上下文中的数据源 -->
<dataSource type="POOLED">
<property name="driver" value="$jdbc.driver"/>
<property name="url" value="$jdbc.url"/>
<property name="username" value="$jdbc.username"/>
<property name="password" value="$jdbc.password"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件 -->
<mappers>
<!-- <mapper resource="mappers/UserMapper.xml"/> -->
<!-- 以包为单位引入映射文件时,目录名(创建目录时以 / 分割而非 .)需与接口所在包名一致且映射文件名也需与接口名一致 -->
<package name="com.bear.mybatis.mapper"/>
</mappers>
</configuration>
1.6 SqlSessionUtils.java
/**
* @author Spring-_-Bear
* @datetime 6/11/2022 10:01 AM
*/
public class SqlSessionUtils
public static SqlSession getSqlSession() throws IOException
// 读取 MyBatis 核心配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 创建 SqlSessionFactoryBuilder 对象以获得 sql 会话工厂对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 获取 sql 会话工厂对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
// 生产会话,传入参数 true,自动提交事务
return sqlSessionFactory.openSession(true);
二、获取参数值
2.1 获取参数的两种方式
$
的本质就是字符串拼接(使用$
时注意添加单引号以处理字符串拼接问题)#
的本质就是占位符赋值
2.2 获取单个字面量参数
<!-- $ 形式获取参数 -->
<!-- User getUserByUsername(String username); -->
<select id="getUserByUsername" resultType="User">
<!-- 花括号中的变量名可任意取,注意单引号问题 -->
select * from t_user where username = '$username'
</select>
<!-- # 形式获取参数 -->
<!-- User getUserByUsername(String username); -->
<select id="getUserByUsername" resultType="User">
<!-- 花括号中的变量名可任意取 -->
select * from t_user where username = #username
</select>
2.3 获取多个字面量参数
MyBatis 底层将参数封装在了 Map 集合中,键为 arg0、arg1······ 或 param1、param2······
<!-- param 从 1 开始计数 -->
<!-- User getUserByUsernameAndPassword(String username, String password); -->
<select id="getUserByUsernameAndPassword" resultType="User">
select * from t_user where username = #param1 and password = #param2
</select>
<!-- arg 从 0 开始计数 -->
<!-- User getUserByUsernameAndPassword(String username, String password); -->
<select id="getUserByUsernameAndPassword" resultType="User">
select * from t_user where username = #arg0 and password = #arg1
</select>
2.4 Map 传参获取参数
// UserMapper.java
List<User> getUserByMapParam(Map<String, String> map);
// UserMapperTest.java
@Test
public void getUserByMap()
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
Map<String, String> paramMap = new HashMap<>();
paramMap.put("username", "admin");
paramMap.put("password", "admin");
List<User> userByMap = mapper.getUserByMap(paramMap);
userByMap.forEach(System.out::println);
<!-- UserMapper.xml -->
<!-- List<User> getUserByMapParam(Map<String, String> map); -->
<select id="getUserByMapParam" resultType="User">
select * from t_user where username = #username and password = #password
</select>
2.5 POJO 对象获取参数
<!-- int saveUser(User user); -->
<insert id="saveUser" >
insert into t_user values (null, #username, #password, #age, #sex, #email)
</insert>
2.6 @Param 命名参数
List<User> login(@Param("username") String username, @Param("password") String password);
<!-- List<User> login(@Param("username") String username, @Param("password") String password); -->
<select id="login" resultType="User">
select * from t_user where username = #username and password = #password
</select>
三、SELECT
3.1 查询用户总记录数
<!-- 使用 MyBatis 中的默认类型别名 integer -->
<!-- int getUserCounts(); -->
<select id="getUserCounts" resultType="integer">
select count(id) from t_user
</select>
3.2 查询结果封装为 Map
-
将数据库表的每个字段依次封装为一条记录
// UserMapper.java List<Map<String, Object>> getAllUsersToMap(); // UserMapperTest.java @Test public void getAllUsersToMap() throws IOException SqlSession sqlSession = SqlSessionUtils.getSqlSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<Map<String, Object>> allUsersToMap = userMapper.getAllUsersToMap(); // Output:username=0121910870207, password=0121910870207 allUsersToMap.forEach(System.out::println);
<!-- UserMapper.xml --> <!-- List<Map<String, Object>> getAllUsersToMap(); --> <select id="getAllUsersToMap" resultType="map"> select * from t_user; </select>
-
以指定的字段为 key,查询结果 POJO 对象为值,封装为 Map
// UserMapper.java @MapKey("real_name") 以上是关于[Study]MyBatis的主要内容,如果未能解决你的问题,请参考以下文章