MyBatis的第一天笔记
1. MyBatis 概述
1.1 什么是框架
- 框架是对通用代码的封装,提前写好了一堆接口和类,可以直接引入使用
- 框架一般以jar包形式存在
- Java常用框架:SSM三大框架(Spring + SpringMVC + MyBatis)、SpringBoot、SpringCloud等
1.2 三层架构
- 表现层(UI):直接与前端交互,接收请求并返回数据
- 业务逻辑层(BLL):处理具体业务,连接表现层和持久层
- 数据访问层(DAL):直接操作数据库完成CRUD操作
- MyBatis属于持久层框架
1.3 JDBC的不足
- SQL语句写死在Java程序中,不灵活
- 给参数赋值过程繁琐
- 结果集封装成Java对象过程繁琐
1.4 MyBatis特点
- 本质是对JDBC的封装
- 半自动化ORM(对象关系映射)框架
- 支持定制化SQL、存储过程、基本映射和高级映射
- 避免了几乎所有JDBC代码的手动设置
- 支持XML开发和注解式开发
- 将接口和Java对象映射成数据库中的记录
- 体积小,易学习:两个jar包,两个XML配置文件
- 完全实现SQL解耦合
2. MyBatis 入门程序
2.1 开发环境
- JDK:Java 21
- MyBatis:3.5.10
- MySQL驱动:8.0.30
- JUnit:4.13.2
- Logback:1.2.11
2.2 关于resources目录
- resources目录中通常放置资源文件和配置文件
- 直接放到resources目录下的资源,等同于放到了类的根路径下
- 从类路径加载资源的好处是项目移植性强,不需要修改代码
2.3 开发步骤详解
-
创建Maven项目,打包方式为jar
-
引入依赖:MyBatis核心依赖和MySQL驱动依赖
<!--mybatis核心依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.10</version> </dependency> <!--mysql驱动依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency>
-
创建MyBatis核心配置文件:mybatis-config.xml
- 文件名不是必须叫做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/数据库名"/> <property name="username" value="用户名"/> <property name="password" value="密码"/> </dataSource> </environment> </environments> <mappers> <mapper resource="XxxMapper.xml"/> </mappers> </configuration>
-
创建SQL映射文件:XxxMapper.xml
- 文件名不是固定的,位置也不是固定的,通常放在类路径下
- 在这个配置文件中编写SQL语句
- SQL语句的结尾分号可以省略
<?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="命名空间"> <insert id="insertXxx"> insert into 表名(字段1,字段2) values(值1,值2) </insert> </mapper>
-
在mybatis-config.xml文件中指定XxxMapper.xml文件的路径
<mapper resource="XxxMapper.xml"/>
- resource属性会自动从类的根路径下开始查找资源
- 也可以使用url属性从绝对路径加载:
<mapper url="file:///d:/XxxMapper.xml"/>
-
编写Java代码,使用MyBatis的核心对象
- SqlSessionFactoryBuilder:构建SqlSessionFactory对象
- SqlSessionFactory:生产SqlSession对象的工厂
- SqlSession:执行SQL语句的核心对象,Java程序和数据库之间的会话
// 1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 2. 创建SqlSessionFactory对象 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is); // 3. 创建SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 4. 执行SQL int count = sqlSession.insert("命名空间.id"); // 5. 提交事务 sqlSession.commit(); // 6. 关闭资源 sqlSession.close();
2.4 关于MyBatis核心配置文件的名字和路径
-
MyBatis的核心文件通常命名为"mybatis-config.xml",但名称不是固定的
-
核心配置文件通常放在类路径下,便于项目移植
-
可以使用Resources类从类路径获取资源:
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
-
也可以使用其他方式获取配置文件:
// 从任意位置获取 InputStream is = new FileInputStream("D:/mybatis-config.xml"); // 使用类加载器获取 InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
2.5 完整的MyBatis程序示例
public class MyBatisCompleteTest {
public static void main(String[] args) {
SqlSession sqlSession = null;
try {
// 1.创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2.创建SqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
// 3.创建SqlSession对象
sqlSession = sqlSessionFactory.openSession();
// 4.执行SQL
int count = sqlSession.insert("insertXxx");
System.out.println("更新了几条记录:" + count);
// 5.提交
sqlSession.commit();
} catch (Exception e) {
// 回滚
if (sqlSession != null) {
sqlSession.rollback();
}
e.printStackTrace();
} finally {
// 6.关闭
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
2.6 使用JUnit进行单元测试
-
引入JUnit依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency>
-
编写测试类
public class XxxMapperTest { @Test public void testInsert(){ SqlSession sqlSession = null; try { // 获取SqlSession并执行SQL // ... } catch (Exception e) { // 异常处理 } finally { // 关闭资源 } } }
2.7 MyBatis的事务管理机制
-
在mybatis-config.xml文件中,可以通过以下配置进行事务管理:
<transactionManager type="JDBC"/>
-
type属性的值包括两个(不区分大小写):
- JDBC:MyBatis框架自己管理事务,使用JDBC原生的事务管理机制
- 底层创建的事务管理器对象是JdbcTransaction
- 通过
conn.setAutoCommit(false)
开启事务 - 通过
conn.commit()
手动提交事务
- MANAGED:MyBatis不再负责事务管理,将事务管理交给其它容器(如Spring)
- 在只有MyBatis的环境下,配置为MANAGED意味着没有人管理事务
- 没有人管理事务就相当于没有事务
- JDBC:MyBatis框架自己管理事务,使用JDBC原生的事务管理机制
-
关于事务的重点:
-
当autoCommit为true时,表示没有开启事务
-
当autoCommit为false时,表示开启了事务
-
在MyBatis中,默认情况下需要手动提交事务:
// 默认开启事务,需要手动提交 SqlSession sqlSession = sqlSessionFactory.openSession(); // 或者创建时指定自动提交(不开启事务) SqlSession sqlSession = sqlSessionFactory.openSession(true);
-
-
SqlSession对象的主要方法:
- 执行SQL语句的方法:
int insert(String statement)
:执行插入SQLint update(String statement)
:执行更新SQLint delete(String statement)
:执行删除SQL<T> T selectOne(String statement)
:执行查询SQL,返回一个对象
- 事务控制方法:
void commit()
:提交事务void rollback()
:回滚事务
- 资源管理方法:
void close()
:关闭会话,释放资源
- 执行SQL语句的方法:
-
事务管理的最佳实践:
-
在实际开发中,建议使用以下代码格式进行事务管理:
SqlSession sqlSession = null; try { // 获取SqlSession对象 sqlSession = sqlSessionFactory.openSession(); // 执行SQL语句 int count = sqlSession.insert("insertCar"); // 提交事务 sqlSession.commit(); } catch (Exception e) { // 回滚事务 if (sqlSession != null) { sqlSession.rollback(); } e.printStackTrace(); } finally { // 关闭资源 if (sqlSession != null) { sqlSession.close(); } }
-
-
事务管理的最佳实践:
-
在实际开发中,建议使用以下代码格式进行事务管理:
SqlSession sqlSession = null; try { // 获取SqlSession对象 sqlSession = SqlSessionFactory.openSession(); // 执行SQL语句 // ... // 提交事务 sqlSession.commit(); } catch (Exception e) { // 回滚事务 if (sqlSession != null) { sqlSession.rollback(); } e.printStackTrace(); } finally { // 关闭资源 if (sqlSession != null) { sqlSession.close(); } }
-
当使用工具类时,可以选择是否开启自动提交:
// 开启自动提交,无需手动提交和回滚 SqlSession sqlSession = SqlSessionUtil.openSession(true); // 或者默认不开启自动提交,需要手动管理事务 SqlSession sqlSession = SqlSessionUtil.openSession();
-
2.8 引入日志框架
2.8.1 使用标准日志
-
在mybatis-config.xml中配置标准日志
<settings> <setting name="logImpl" value="STDOUT_LOGGING" /> </settings>
-
这个配置应该放在environments标签之前
2.8.2 集成logback日志框架
-
引入logback依赖
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> <scope>test</scope> </dependency>
-
创建logback.xml配置文件并放在类路径下
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!--mybatis log configure--> <logger name="com.apache.ibatis" level="TRACE"/> <logger name="java.sql.Connection" level="DEBUG"/> <logger name="java.sql.Statement" level="DEBUG"/> <logger name="java.sql.PreparedStatement" level="DEBUG"/> <!-- 日志输出级别 --> <root level="DEBUG"> <appender-ref ref="STDOUT"/> </root> </configuration>
-
注意事项:
- logback配置文件名必须是logback.xml或logback-test.xml
- 配置文件必须放在类路径下
- logback日志级别包括:TRACE < DEBUG < INFO < WARN < ERROR
2.9 MyBatis工具类SqlSessionUtil的封装
为了简化获取SqlSession对象的过程,可以封装一个工具类:
public class SqlSessionUtil {
private SqlSessionUtil() {};
private static SqlSessionFactory sqlSessionFactory;
/**
* 类加载时初始化sqlSessionFactory对象
*/
static {
try {
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取会话对象,该会话默认开启自动提交
*
* @return 新的会话对象
*/
public static SqlSession openSession() {
return sqlSessionFactory.openSession(true);
}
/**
* 获取会话对象,参数决定是否自动提交
*
* @param autoCommit 是否自动提交
* @return 新的会话对象
*/
public static SqlSession openSession(boolean autoCommit) {
return sqlSessionFactory.openSession(autoCommit);
}
}
使用工具类简化测试代码:
@Test
public void testInsert(){
SqlSession sqlSession = SqlSessionUtil.openSession();
// 执行SQL
int count = sqlSession.insert("insertCar");
System.out.println("插入了几条记录:" + count);
sqlSession.close();
}