1、本篇博客的背景和目的
目前我本人正在学习MyBatis框架,在原先了解并且懵懵懂懂使用的基础上,开始系统正式的学习。目前已经阐述了MVC架构模式和三层架构,明晰了在Web项目中的普遍编码层次,认识了框架,回顾了JDBC连接数据库,介绍了MyBatis框架,初步建立了使用MyBatis和MySQL的Maven项目,简单解释了STDOUT_LOGGING日志和INSERT语句手动提交事务,记录了MyBatis中#占位符的使用方法,回顾了MyBatis执行SQL语句的过程和使用到的一些重要类和接口。本篇博客记录将一些固定化的代码整合到一个工具类MyBatisUtil中,以减少代码量。
2、为什么使用工具类MyBatisUtil呢?
我们在使用MyBatis的时候,如果需要执行一个SQL语句,总是需要加载总配置文件,然后创建SqlSessionFactoryBuilder对象,SqlSessionFactory对象,SqlSession对象。由于SqlSession不是线程安全的,因此每次需要执行SQL语句的时候,都需要新创建一个SqlSession对象。如果在不同的类中要执行SQL语句,上面的过程代码是不是需要重写很多遍啊!!!尽管我们可以复制粘贴,但是代码量很多啊!!!
那么,我们能不能将上面的过程代码作为一个行为方法封装到一个工具类里面呢?当我们需要执行SQL语句的时候,只需要在类中new出来一个工具类对象,然后调用这个行为方法之后就得到一个SqlSession对象呢?所以:MyBatisUtil工具类就诞生了!!
3、我的代码文件结构
项目文件结构如下图所示:
4、 POM文件代码内容
POM文件代码如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dcy</groupId>
<artifactId>MyBatis20220728</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- 单元测试的依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 引入MyBatis的jar包的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- MySQL驱动jar包的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<!-- 所在的目录-->
<directory>src/main/java</directory>
<includes><!-- 这个目录下的所有.xml,.properties文件都会被扫描加载到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
里面的依赖就是测试的junit依赖,mybatis的依赖,MySQL数据库驱动的依赖。最后由于mapper.xml文件没有写在resources目录下,因此需要有resources标签说明一下。
5、MyBatis总配置文件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>
<!-- 下面设置一下日志,一定要在最上面, 其实我们可以按着Ctrl键,鼠标左击configuration标签,进去看它规定的标签顺序-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<!-- 下面是配置一下数据源,其实后面我们就不这样配置了,都在.yml文件中配置-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Hongkong&allowMultiQueries=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 用于指定其它mapper.xml文件的位置,也就是路径
这个路径是从target/classes根路径开始的,也即是com/**/**/这样的
使用注意:使用 / 分隔路径;一个mapper标签指定一个文件;
-->
<mappers>
<mapper resource="com/dcy/dao/StudentDao.xml"></mapper>
</mappers>
</configuration>
6、StudentDao.xml文件代码(也就是不在resources目录下的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="com.dcy.dao.StudentDao">
<!--
select标签表示的是查询操作,里面是查询语句。
id属性的值是SQL语句的唯一标识,是一个自定义的字符串。
按照编码规范,这里统一推荐使用dao接口中对应的方法名称。
resultType属性是表示执行SQL语句后,结果对应那个类型的JAVA对象。resultType的值是某个实体类的全限定名称。
比如:com.dcy.domain.Student
-->
<select id="selectById" resultType="com.dcy.domain.Student">
<!--select id,name,email,age from student where id=1001-->
select id,name,email,age from student where id=#{studentId}
</select>
<!-- 下面的语句使用了占位符,因为我们传过来的是一个java对象,可以直接使用它的属性名,放在花括号里面,
前面配上#,这就相当于是传参了-->
<insert id="insertStudent">
insert into student values (#{id},#{name},#{email},#{age})
</insert>
<select id="selectStudents" resultType="com.dcy.domain.Student">
select * from student
</select>
</mapper>
7、dao层的接口StudentDao文件(其实这个文件目前没有实际作用)
package com.dcy.dao;
import com.dcy.domain.Student;
import java.util.List;
public interface StudentDao {
public Student selectById(Integer id);
public List<Student> selectStudents();
public int insertStudent(Student student);
}
8、Student实体类,对应数据库中的student表
package com.dcy.domain;
public class Student {
//这里我们的属性名和数据库表中的列名保持一致,如果不一致的话我们需要在mapper.XML文件中配置或者是使用注解配置
private Integer id;
private String name;
private String email;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "一个学生实体的信息{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", age=" + age +
'}';
}
}
9、数据表student
这里我截一下图片,只展示表中字段名和字段类型:
10、工具类MyBatisUtil代码
package com.dcy.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;
import java.io.IOException;
import java.io.InputStream;
/*
这个类是一个工具类,是为了解决 使用MyBatis执行SQL语句之前需要准备的对象太多的问题
*/
public class MyBatisUtil {
/*
静态代码块只会执行一次,在加载类的时候执行,先于Main方法执行
*/
private static SqlSessionFactory factory=null;
static {
String config="mybatis.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(config);
factory= new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//下面创建方法来获取SqlSession对象
public static SqlSession getSqlSession(){
SqlSession sqlSession=null;
if (factory!=null){//说明存在SqlSessionFactory对象
sqlSession=factory.openSession(true);//自动提交事务
}
return sqlSession;
}
}
首先是一个静态代码块。静态代码块只会执行一次,并且是在加载类的时候执行,先于Main方法执行。也就是我们启动项目以后,由于静态代码块的存在,这个类中就已经加载好了SqlSessionFactory这个对象,并且只有一个此对象。
然后又写了一个静态方法,我们只需要使用类名就可以调用这个方法,然后获得一个自动提交事务的SqlSession对象,然后可以使用这个对象的方法执行SQL语句。
11、在Main方法中进行测试
package com.dcy;
import com.dcy.domain.Student;
import com.dcy.utils.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
public class starter {
public static void main(String[] args) {
//获取SqlSession对象
SqlSession sqlSession= MyBatisUtil.getSqlSession();
//拿到要执行的SQL语句的“地址”
String SqlId="com.dcy.dao.StudentDao"+"."+"selectStudents";
//执行SQL语句并拿到执行结果
List<Student> students = sqlSession.selectList(SqlId);
System.out.println(students);
//关闭SqlSession对象
sqlSession.close();
}
}
上面代码比较简单,我不多解释了,运行后控制台的结果如下所示:
因为在总配置文件中开启了STDOUT_LOGGING日志,所以打印的有日志。
12、我的上一篇博文
上一篇博文解释了MyBatis执行SQL的具体过程和需要使用到的一些重要类和对象,感兴趣的读者可以移步阅读,链接如下: