二、MyBatis入门程序
2.1 MyBatis入门程序开发步骤
-
写代码前准备:
-
准备数据库表:汽车表t_car,字段包括:
- id:主键(自增)【bigint】
- car_num:汽车编号【varchar】
- brand:品牌【varchar】
- guide_price:厂家指导价【decimal类型,专门为财务数据准备的类型】
- produce_time:生产时间【char,年月日即可,10个长度,‘2022-10-11’】
- car_type:汽车类型(燃油车、电车、氢能源)【varchar】
-
使用navicat for mysql工具建表
-
使用navicat for mysql工具向t_car表中插入两条数据,如下:
-
创建Project:建议创建Empty Project,设置Java版本以及编译版本等。
-
设置IDEA的maven
-
创建Module:普通的Maven Java模块
-
-
步骤1:打包方式:jar(不需要war,因为mybatis封装的是jdbc。)
<groupId>com.mybatis-study</groupId>
<artifactId>mybatis-001-introduction</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
- 步骤2:引入依赖(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>
- 步骤3:在resources根目录下新建mybatis-config.xml配置文件(可以参考mybatis手册拷贝)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//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-study"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><!--sql映射文件创建好之后,需要将该文件路径配置到这里--><mapper resource=""/></mappers>
</configuration>
注意1:mybatis核心配置文件的文件名不一定是mybatis-config.xml
,可以是其它名字。
注意2:mybatis核心配置文件存放的位置也可以随意。这里选择放在resources
根下,相当于放到了类的根路径下。
- 步骤4:在
resources
根目录下新建CarMapper.xml
配置文件(可以参考mybatis手册拷贝)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先随意写一个-->
<mapper namespace="car"><!--insert sql:保存一个汽车信息--><insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values(null,'102','丰田mirai',40.30,'2014-10-05','氢能源')</insert>
</mapper>
注意1:sql语句最后结尾可以不写“;
”
注意2:CarMapper.xml
文件的名字不是固定的。可以使用其它名字。
注意3:CarMapper.xml
文件的位置也是随意的。这里选择放在resources根下,相当于放到了类的根路径下。
注意4:将CarMapper.xml
文件路径配置到mybatis-config.xml
:
<mapper resource="CarMapper.xml"/>
- 步骤5:编写
MyBatisIntroductionTest
代码
package com.study.mybatis;import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.InputStream;/*** MyBatis入门程序* @author sqnugy* @since 1.0* @version 1.0*/
public class MyBatisIntroductionTest {public static void main(String[] args) {// 1. 创建SqlSessionFactoryBuilder对象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// 2. 创建SqlSessionFactory对象InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);// 3. 创建SqlSession对象SqlSession sqlSession = sqlSessionFactory.openSession();// 4. 执行sqlint count = sqlSession.insert("insertCar"); // 这个"insertCar"必须是sql的idSystem.out.println("插入几条数据:" + count);// 5. 提交(mybatis默认采用的事务管理器是JDBC,默认是不提交的,需要手动提交。)sqlSession.commit();// 6. 关闭资源(只关闭是不会提交的)sqlSession.close();}
}
注意1:默认采用的事务管理器是:JDBC。JDBC事务默认是不提交的,需要手动提交。
- 步骤6:运行程序,查看运行结果,以及数据库表中的数据
2.2 MyBatis第一个比较完整的代码写法
package com.study.mybatis;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;/*** 比较完整的第一个mybatis程序写法* @author sqnugy* @since 1.0* @version 1.0*/
public class MyBatisCompleteCodeTest {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.执行SQLint count = sqlSession.insert("insertCar");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.3 引入JUnit
- JUnit是专门做单元测试的组件。
- 在实际开发中,单元测试一般是由我们Java程序员来完成的。
- 我们要对我们自己写的每一个业务方法负责任,要保证每个业务方法在进行测试的时候都能通过。
- 测试的过程中涉及到两个概念:
- 期望值
- 实际值
- 期望值和实际值相同表示测试通过,期望值和实际值不同则单元测试执行时会报错。
- 这里引入JUnit是为了代替main方法。
- 使用JUnit步骤:
- 第一步:引入依赖
<!-- junit依赖 -->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>
- 第二步:编写单元测试类【测试用例】,测试用例中每一个测试方法上使用@Test注解进行标注。
- 测试用例的名字以及每个测试方法的定义都是有规范的:
- 测试用例的名字:XxxTest
- 测试方法声明格式:public void test业务方法名(){}
- 测试用例的名字以及每个测试方法的定义都是有规范的:
// 测试用例
public class CarMapperTest{// 测试方法@Testpublic void testInsert(){}@Testpublic void testUpdate(){}}
- 第三步:可以在类上执行,也可以在方法上执行
- 在类上执行时,该类中所有的测试方法都会执行。
- 在方法上执行时,只执行当前的测试方法。
- 编写一个测试用例,来测试insertCar业务
package com.study.mybatis;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 org.junit.Test;public class CarMapperTest {@Testpublic void testInsertCar(){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.执行SQLint count = sqlSession.insert("insertCar");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.4 引入日志框架logback
- 引入日志框架的目的是为了看清楚mybatis执行的具体sql。
- 启用标准日志组件,只需要在mybatis-config.xml文件中添加以下配置:【可参考mybatis手册】
<settings><setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
标准日志也可以用,但是配置不够灵活,可以集成其他的日志组件,例如:log4j,logback等。
- logback是目前日志框架中性能较好的,较流行的,所以我们选它。
- 引入logback的步骤:
- 第一步:引入logback相关依赖
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version><scope>test</scope>
</dependency>
- 第二步:引入logback相关配置文件(文件名叫做logback.xml或logback-test.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><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名--><FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern><!--日志文件保留天数--><MaxHistory>30</MaxHistory></rollingPolicy><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><!--日志文件最大的大小--><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>100MB</MaxFileSize></triggeringPolicy></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"/><!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>
- 再次执行单元测试方法testInsertCar,查看控制台是否有sql语句输出
2.5 MyBatis工具类SqlSessionUtil的封装
- 每一次获取SqlSession对象代码太繁琐,封装一个工具类
package com.study.mybatis.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;/*** MyBatis工具类** @author sqnugy* @version 1.0* @since 1.0*/
public class 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();}}/*** 每调用一次openSession()可获取一个新的会话,该会话支持自动提交。** @return 新的会话对象*/public static SqlSession openSession() {return sqlSessionFactory.openSession(true);}
}
- 测试工具类,将testInsertCar()改造
@Test
public void testInsertCar(){SqlSession sqlSession = SqlSessionUtil.openSession();// 执行SQLint count = sqlSession.insert("insertCar");System.out.println("插入了几条记录:" + count);sqlSession.close();
}** @return 新的会话对象*/public static SqlSession openSession() {return sqlSessionFactory.openSession(true);}
}
- 测试工具类,将testInsertCar()改造
@Test
public void testInsertCar(){SqlSession sqlSession = SqlSessionUtil.openSession();// 执行SQLint count = sqlSession.insert("insertCar");System.out.println("插入了几条记录:" + count);sqlSession.close();
}