前言
MyBatis 是一个半 ORM(对象关系映射)框架,它内部封装了 JDBC,开发时只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 sql,可以严格控制 sql 执行性能,灵活度高。
MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
一、什么是ORM?
ORM(Object Relational Mapping),即对象关系映射,是一种为了解决关系型数据库数据与简单 Java 对象(POJO)的映射关系的技术。简单来说,ORM 是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。
1.1 为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 SQL 来完成,所以,被称之为半自动 ORM 映射工具。下图是ORM简单示意图:
1.2 JDBC 编程有哪些不足之处,MyBatis 是如何解决这些缺点的?
bash
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author ZhangXu
* @date 2024/4/2515:40
* @Description:
*/
public class Dmeo3 {
public static void main(String[] args) throws SQLException {
//1创建dataSource
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setURL("Jdbc:mysql://127.0.0.1:3306/java110?characterEncoding utf8&useSSL = false");
((MysqlDataSource)dataSource).setUser("root");
((MysqlDataSource)dataSource).setPassword("123456");
//2.建立连接
Connection connection = dataSource.getConnection();
//3.构造sql
String sql = "select * from student";
PreparedStatement statement = connection.prepareStatement(sql);
//4.执行sql
//ResultSet表示查询的集合(临时表),此处需要针对表进行遍历
ResultSet resultSet =statement.executeQuery(); //获取集合
//5.遍历结果结合
//通过next 方法就可以获得临时表中的每一行数据,获取到最后一行数据后,再执行next返回false,循环结束
while(resultSet.next()){
//针对这一行进行处理
//取出列中的数据
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("id:"+id+",name:"+name);
}
//6.释放资源
statement.close();
statement.close();
connection.close();
}
}
- 数据连接创建、释放频繁造成系统资源浪费从而影响系统性能,在 mybatis-config.xml 中配置数据链接池,使用连接池统一管理数据库连接。
- sql 语句写在代码中造成代码不易维护,将 sql 语句配置在 XXXXmapper.xml 文件中与 java 代码分离。
- 向 sql 语句传参数麻烦,因为 sql 语句的 where 条件不一定,可能多也可能少,占位符需要和参数一一对应。Mybatis 自动将 java 对象映射至 sql 语句。
- 对结果集解析麻烦,sql 变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo 对象解析比较方便。Mybatis 自动将 sql 执行结果映射至 java 对象
二、MyBatis 使用过程?生命周期?
MyBatis 基本使用的过程大概可以分为这么几步:
1. 创建 SqlSessionFactory
可以从配置或者直接编码来创建 SqlSessionFactory
bash
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
2. 通过 SqlSessionFactory 创建 SqlSession
SqlSession(会话)可以理解为程序和数据库之间的桥梁
bash
SqlSession session = sqlSessionFactory.openSession();
3. 通过 sqlsession 执行数据库操作
可以通过 SqlSession 实例来直接执行已映射的 SQL 语句:
bash
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
4. 调用 session.commit()提交事务
如果是更新、删除语句,我们还需要提交一下事务。
5. 调用 session.close()关闭会话
最后一定要记得关闭会话。
三、 mapper 中如何传递多个参数?
方法 1:顺序传参法
bash
public User selectUser(String name, int deptId);
<select id="selectUser" resultMap="UserResultMap">
select * from user
where user_name = #{0} and dept_id = #{1}
</select>
#{}里面的数字代表传入参数的顺序。
这种方法不建议使用,sql 层表达不直观,且一旦顺序调整容易出错
方法 2:@Param 注解传参法
bash
public User selectUser(@Param("userName") String name, int @Param("deptId") deptId);
<select id="selectUser" resultMap="UserResultMap">
select * from user
where user_name = #{userName} and dept_id = #{deptId}
</select>
#{}里面的名称对应的是注解@Param 括号里面修饰的名称。
这种方法在参数不多的情况还是比较直观的,(推荐使用)
Map 传参法
bash
public User selectUser(Map<String, Object> params);
<select id="selectUser" parameterType="java.util.Map" resultMap="UserResultMap">
select * from user
where user_name = #{userName} and dept_id = #{deptId}
</select>
#{}里面的名称对应的是 Map 里面的 key 名称。
这种方法适合传递多个参数,且参数易变能灵活传递的情况
方法 4:Java Bean 传参法
bash
public User selectUser(User user);
<select id="selectUser" parameterType="com.jourwon.pojo.User" resultMap="UserResultMap">
select * from user
where user_name = #{userName} and dept_id = #{deptId}
</select>
#{}里面的名称对应的是 User 类里面的成员属性。
这种方法直观,需要建一个实体类,扩展不容易,需要加属性,但代码可读性强,业务逻辑处理方便,推荐使用。(推荐使用)