1、MyBatis简介
1.1MyBatis特性
- MyBatis是一款优秀的半自动的持久层框架,用于简化JDBC的开发;
- MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架;
- MyBatis免除了几乎所有的JDBC代码以及手动设置参数和获取结果集;
- MyBatis采用.xml配置文件或者注解的方式实现增删改查等各种操作,将接口和java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。
1.2 、Mybatis下载
MyBatis下载官网:https://github.com/mybatis/mybatis-3
1.3和JDBC持久化层技术对比
JDBC
- JDBC的SQL夹杂在Java代码中耦合度高,导致硬编码内伤;
- 代码冗长,开发效率低
- JDBC存在硬编码(需进行注册驱动,获取连接,编写SQL语句)问题,以及操作繁琐(需要手动设置参数以及手动封装结果集)
MyBatis
- 轻量级,性能出色;
- SQL和Java编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据;
- 开发效率稍逊于HIbernate,但是完全能够接受
2、搭建MyBatis
2.1、开发环境
IDE:IDEA 2021.1.3
构建工具:maven 3.5.4
MySQL版本:MySQL 8或MYSQL 5
MyBatis版本:MyBatis 3.5.7
MySQL不同版本的注意事项
1、驱动类driver-class-name
MySQL 5版本:com.mysql.jdbc.Driver
MySQL 8版本:com.mysql.cj.jdbc.Driver
2、连接地址url
MySQL 5版本:jdbc:mysql://localhost:3306/数据库名?useSSL=false&characterEncoding=UTF-8
MySQL 8版本:jdbc:mysql://localhost:3306/数据库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTime=UTC
2.2创建maven工程
创建maven工程有两种方式
1)打包方式:jar
2)引入依赖
<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.11</version>
</dependency>
<!-- MySQL驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- lombok依赖 导入依赖时要下载创建Lombok -->
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok-maven-plugin -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.12.0</version>
</dependency>
</dependencies>
<!--静态资源的导出问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
2.3、创建MyBatis的核心配置文件
- 习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合Spring之后,这个配置文件可以省略。
- 核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息;
- 核心配置文件存放的位置是src/main/resources目录下
- XML配置文件中包含了对MyBatis系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
<?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>
<!-- environment: 配置数据库连接环境信息,可以配置多个environment,通过切换不同的environment -->
<environments default="development">
<!-- 数据源 -->
<environment id="development">
<!-- 事务管理器的配置 type的属性值有:jdbc/managed-->
<transactionManager type="JDBC"/>
<!-- 连接池配置 数据库连接信息 数据源的配置 type="pooled" -->
<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>
<!-- 指定sql映射文件的路径 mapper为映射器 -->
<mappers>
<!-- 加载sql的映射文件-->
<!-- resource 的属性值为 xml文件的路径 从src/main/java之后开始-->
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
2.4、创建mapper接口
MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。
public interface UserMapper {
/**
* 查询用户信息
*/
public List<User> QueryAllUser();
}
2.5、创建MyBatis的映射文件
概念:ORM,对象关系的映射。
- 对象:Java的实体类对象
- 关系:关系型数据库
- 映射:二者之间的对应关系
Java概念 | 数据库概念 |
---|---|
类 | 表 |
属性 | 字段/列 |
对象 | 记录/行 |
1、映射文件的命名规则:
表所对应的实体类的类名+Mapper.xml
例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml
所以一个映射文件对应一个实体类,对应一张表的操作
MyBatis映射文件用于编写SQL,访问以及操作表中的数据
MyBatis映射文件存放的位置为src/main/resources/mappers目录下
2、MyBatis中可以面向接口操作数据,要保证两个一致;
<1>mapper接口的全类名和映射文件的命名空间(namespace) 保持一致
<2>mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致
<?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="org.mybatis.example.BlogMapper">
<select id=" QueryAllUser" resultType="User">
select * from Blog where id = #{id}
</select>
</mapper>
2.6、通过junit测试功能
//1.获取核心配置文件的输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
//2.获取SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder 为工厂对象 使用的是工厂模式
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//获取SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//3、获取sql的会话对象SqlSession(不会提交事务),是MyBatis提供的操作数据库的对象 必须手动提交事务
// SqlSession session = sqlSessionFactory.openSession();
//3、获取sql的会话对象SqlSession(会提交事务),是MyBatis提供的操作数据库的对象
SqlSession session = sqlSessionFactory.openSession(true);
//4、获取UserMapper的代理实现类对象
UserMapper mapper = session.getMapper(UserMapper.class);
//5、调用mapper接口中的方法,实现添加用户信息的功能
int result= mapper.insertUser();
//4、5、提供sql以及的唯一标识找到sql并执行,唯一标识是namespace.sqlId
// int result = session.insert("com.atguigu.mybatis.mapper.UserMapper.insertUser");
System.out.println("结果: " + result);
//提交事务
// session.commit();
//关闭资源
session.close();
- SqlSession:代表Java程序和数据库之间的会话。
- SqlSessionFactory:是生产SqlSession的“工厂”
- 工厂模式:如果创建某一对象,使用的过程基本稳定,那么我们就可以把创建这个对象的相关代码封装到一个“工厂类"中,以后都使用这个工厂类来生产我们需要的对象。
2.7、加入slf4j日志功能
1、加入依赖jar包
<!-- 添加slf4j日志api-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.20</version>
</dependency>
<!-- 添加logback-classic依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 添加logback-core依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
2、加入日志slf4j的配置文件
slf4j的配置文件名为logback.xml,存在的位置是src/main/resources目录下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--
CONSOLE :表示当前的日志信息是可以输出到控制台的。
-->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg %n</pattern>
</encoder>
</appender>
<logger name="com.itheima" level="DEBUG" additivity="false">
<appender-ref ref="Console"/>
</logger>
<!--
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF
, 默认debug
<root>可以包含零个或多个<appender-ref>元素,标识这个输出位置将会被本日志级别控制。
-->
<root level="DEBUG">
<appender-ref ref="Console"/>
</root>
</configuration>
3、MyBatis获取参数值的两种方式
MyBatis获取参数值的两种方式:${}和#{}
${}的本质就是字符串拼接,#{}的本质就是占位符赋值
${}使用字符串拼接方式拼接sql,若为字符串型或日期类型的字段进行赋值时,需要手动加添单引号;但是**#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号**
3.1、单个字面量类型的参数
若mapper接口中的方法参数为单个的字面类型
此时可以使用${}和#{}以任意的名称获取参数的值,注意${}需要手动添加单引号
3.2、多个字面量类型的参数
若mapper接口中的方法参数为多个时
此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1....为键,以参数为值;以param1,param2....为键,以参数为值;所以直选哟通过${}和#{}访问map集合的键就可以获取对应的值,注意${}需要手动添加单引号
3.3、map集合类型的参数
若mapper接口中的方法需要的参数为多个时,
此时可以手动创建map集合,将这些数据放在map中,只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动添加单引号
3.4、实体类类型的参数
若mapper接口方法的参数为实体类类型的参数
只需要通过#{}和${}访问实体类中的属性名(属性名只跟get和set方法有关),就可以获取相对应的属性值,一定要注意${}的单引号问题
3.5、使用@Param标识参数
可以在mapper接口方法的参数上设置@Param注解
此时MyBatis会将这些参数放在map中,以两种方式进行存储
a>以@Param注解的value属性值为键,以参数为值
b>以param1、param2....为键,以参数为值
只需要通过#{}和${}访问map集合的键,就可以获取相对于的值,一定要注意${}的单引号问题
4、MyBatis的各种查询功能
4.1、查询一个实体类对象
/**
* 根据id查询用户信息
* @param id
* @return
*/
public User getUserById(@Param("id") Integer id);
<!-- public User getUserById(@Param("id") Integer id);-->
<select id="getUserById" resultType="user">
select * from t_user where id = #{id}
</select>
4.2、查询一个list集合
/**
* 查询所有的用户信息
* @return
*/
List<User> getAllUser();
<!-- List<User> getAllUser();-->
<select id="getAllUser" resultType="user">
select * from t_user
</select>
* 若sql语句查询的结果为多条时,一定不能以实体类型作为方法的返回值
* 否则会抛出异常ToolManyResultsException
* 若sql语句查询的结果为一条时,此时可以使用实体类类型或list集合类型作为方法的返回值
4.3、查询一条数据为map集合
/**
* 根据id查询用户信息为map集合
* @param id
* @return
*/
Map<String,Object> getUserByIdTomap(@Param("id") Integer id);
<!-- 根据id查询用户信息为map集合-->
<select id="getUserByIdTomap" resultType="map">
select * from t_user where id = #{id};
</select>
4.4、查询多条数据为map集合
若查询的数据为多条时,并且要将每条数据转换为map集合
* 此时有两种解决方案:
* 1.将mapper接口方法的返回值设置为泛型是map的list集合
* 2.可以将每条数据转换的map集合放在一个大的map集合中,但是必须要通过@MapKey注解将查询的某个字段的值作为大的map的键
/**
* 查询所有的用户信息为map集合
* @return
* @MapKey注解:把当前查询的数据所转换的map集合放在一个大的Map集合中,然后通过此注解可以设置map集合的键
*/
//方法一
// List<Map<String,Object>> getAllUserToMap();
//方法二
//把字段id作为大的map集合的键,其值为每一条数据所转换的map集合
@MapKey("id")
Map<String,Object> getAllUserToMap();
<!-- 查询所有的用户信息为map集合-->
<select id="getAllUserToMap" resultType="map">
select * from t_user
</select>
//方法一
// List<Map<String, Object>> list = mapper.getAllUserToMap();
// System.out.println(list);
//方法二
Map<String, Object> allUserToMap = mapper.getAllUserToMap();
System.out.println(allUserToMap);
/**
* 输出结果为: id的值为键,每一条map集合为值
* {1={password=123456, gender=男, id=1, age=23, email=12345@qq.com, username=admin}, 2={password=123456, gender=男, id=2, age=23, email=12345@qq.com, username=admin},}
*/
5、特殊SQL的执行
5.1、模糊查询
/**
*通过用户名模糊查询用户信息
* @param mohu
* @return
*/
List<User> getuserLike(@Param("mohu") String mohu);
<!-- *通过用户名模糊查询用户信息 -->
<select id="getuserLike" resultType="user">
select * from t_user
<!-- where username like "%"#{mohu}"%"; -->
<!-- $ 表示字符串拼接 -->
<!-- where username like '%${mohu}%'; -->
<!-- concat 字符串拼接的函数 -->
where username like concat('%',#{mohu},'%');
</select>
5.2、批量删除
/**
* 批量删除
* @param ids
*/
void deleteMoreUser(@Param("ids") String ids);
<!-- 批量删除 ids:8,9 id in('8,9')-->
<delete id="deleteMoreUser">
delete from t_user where id in(${ids})
</delete>
5.3、动态设置表名
/**
* 动态设置表名,查询用户信息
* @param tableName
* @return
*/
List<User> getUserList(@Param("tableName") String tableName);
<!-- List<User> getUserList(@Param("tableName") String tableName); -->
<select id="getUserList" resultType="user">
<!-- 不能使用#,只能使用$ -->
select * from ${tableName}
</select>
//* 动态设置表名,查询用户信息
@Test
public void testGetUserList() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
// 表名t_user
List<User> list = mapper.getUserList("t_user");
list.forEach(System.out::println);
}
5.4、添加功能获取自增的主键
/**
* 添加用户信息
* @param user
* @return
* useGenerateKeys:设置使用自增的主键
* keyProperty:由于增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
*/
void insertUser(User user);
<!-- * 添加用户信息并获取自增的主键-->
<!--
useGeneratedKeys:表示当前添加功能使用自增的主键
keyProperty:将添加的数据的自增主键为实体类的参数的属性进行赋值
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email});
</insert>
// * 添加用户信息并获取自增的主键
@Test
public void testInsertUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
User user = new User(null,"xiaoming","123456",23,"男","12345@qq.com");
mapper.insertUser(user);
System.out.println(user);
}