Mybatis
- MyBatis本质上就是对JDBC的封装,通过MyBatis完成CRUD。
- 而对于JDBC,SQL语句写死在Java程序中,不灵活。改SQL的话就要改Java代码。违背开闭原则OCP。
- 对于事务机制,MyBatis支持 或managed模式,JDBC模式中MyBatis将事物委托给JDBC管理;managed模式中MyBatis不再管理事务,此时可以使用Spring框架等管理事务;否则,程序根本不支持事务,这是不推荐的。
- MyBatis属于半自动化ORM框架,虽然不会全自动生成,但是可调行高,易于debug。
- 将接口和 Java 的 POJOs(Plain Ordinary Java Object,简单普通的Java对象)映射成数据库中的记录
1.新建Mybatis项目
●步骤1:pom.xml中声明打包方式:jar(不需要war,因为mybatis封装的是jdbc。)
●步骤2:引入依赖(mybatis依赖 + mysql驱动依赖)
●步骤3:在resources根目录下新建mybatis-config.xml配置文件(可以参考mybatis手册拷贝)
注意1:mybatis核心配置文件的文件名不一定是mybatis-config.xml,可以是其它名字。
注意2:mybatis核心配置文件存放的位置也可以随意。这里选择放在resources根下,相当于放到了类的根路径下。
●步骤4:在resources根目录下新建CarMapper.xml配置文件(可以参考mybatis手册拷贝)
注意1:sql语句最后结尾可以不写";"
注意2:CarMapper.xml文件的名字不是固定的。可以使用其它名字。
注意3:CarMapper.xml文件的位置也是随意的。这里选择放在resources根下,相当于放到了类的根路径下。
注意4:将CarMapper.xml文件路径配置到mybatis-config.xml:
●步骤5:编写mybatis程序myBatisIntroductionTest代码
注意1:默认采用的事务管理器是:JDBC。JDBC事务默认是不提交的,需要手动提交。
注意2:在mybatis中,执行sql语句的对象叫做SqlSession,是Java程序和数据库之间的一次会话.
而要获取SqlSession对象--先获取SqlSessionFactory对象--通过SqlSessionFactoryBuilder对象的Build方法,获取一个SqlSessionFactory对象.
●步骤6:运行程序,查看运行结果,以及数据库表中的数据
结构为
新建一个空项目,然后新建一个空白模块
项目设置中更改默认Maven设置,setting.xml设置
pom.xml中添加打包方式,依赖(mybatis,mysql)
xml
<packaging>jar</packaging>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-java -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
在Main根目录下resources文件夹新建 mybatis-config.xml 文件(mybatis核心配置文件,只有一个)
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/carreseller}"/>
<property name="username" value="${root}"/>
<property name="password" value="${Mysql998168}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 说明欲执行的mapper文件的存放位置-->
<!-- 从根目录下开始查找,因此如果mapper文件就放在根目录下,则不用写出具体路径-->
<mapper resource="CarMapper.xml"/>
</mappers>
</configuration>
编写xxxMapper.xml(mybatis配置文件,多个,每个mapper文件对应一个表)
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">
<mapper namespace="TBD">
<insert id="">
insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)
values(null,'1003','toyota',30.00,'2000-10-11','燃油车')
</insert>
</mapper>
java
package com.sunsplanter.mybatis.test;
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.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisIntroductionTest {
public static void main(String[] args) throws IOException {
SqlSession sqlSession = null;
try {
// 获取对象的顺序为:SqlSessionFactoryBuilder-》SqlSessionFactory-》SqlSession
//每个数据库中,这三者的关系是:1:1:n
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//MyBatis包含了一个Resources类,用Resources类调方法,默认从类的根目录下开始找,因此如果mybatis-config.xml就放在Resources目录下,直接写名字就可以
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");//mybatis核心配置文件的路径
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
sqlSession = sqlSessionFactory.openSession();
//执行SQL语句,执行的语句在xxxMapper.xml中,并且并非一次执行完一个Mapper的全部代码
// 因此通过id为参数,定位要执行的具体SQL代码块
//insert可选返回值,返回值代表影响数据库中表项的个数.
int count = sqlSession.insert("insertCar");
System.out.println(count);
//当mybatis-config.xml中<transactionManager type="JDBC"/>时,即将事务机制交给JDBC管理
//而JDBC的autoCommit是false的,因此必须要sqlSession.commit手动提交,因此说此时sqlSession对象不支持自动提交。
sqlSession.commit();
} catch (Exception e) {
// 回滚
if (sqlSession != null) {
sqlSession.rollback();
}
e.printStackTrace();
} finally {
// 6.关闭
if (sqlSession != null) {
sqlSession.close();
}
}
}
}
引入Junit
引入Junit是为了替代main方法,可以单独测试各个单元。
● 使用JUnit步骤:
○ 第一步:引入依赖
xml
<!-- 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{
// 测试方法
@Test
public void testInsert(){}
@Test
public void testUpdate(){}
}
○ 第三步:可以在类上执行,也可以在方法上执行
■ 在类上执行时,该类中所有的测试方法都会执行。
■ 在方法上执行时,只执行当前的测试方法。
引入日志文件
在mybatis-config.xml中的environments 标签前,可添加settings标签(若有,则相对位置必须要settings在前),是否开启日志,开启何种日志,就是其中一种setting。
logback作为一个框架,实现了SLF4J标准,因此,尽管setting中选择的日志是SLF4J,等会导入依赖还是导入logback。
xml
<settings>
<setting name="logImpl" value="SLF4J" />
</settings>
使用logback,先添加依赖
xml
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
<scope>test</scope>
</dependency>
logback实现(包含了SLF4J),从依赖的关系中就可以看出来:
第二步:引入logback相关配置文件(文件名必须叫做logback.xml或logback-test.xml,放到类路径当中)
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>
此时再次执行代码,控制台会输出更详细的反馈,包括执行了哪条SQL语句。