简单配置让MyBatis跑起来
这一节将通过一个 MyBatis 的简单例子让大家对 MyBatis 有一个初步的了解。在操作过程中,建议初学者按照书中的步骤进行,如果已经了解各项配置之间的关系,也可以按照自己习惯的方式对配置进行调整。
准备数据库
首先创建一个数据库,编码方式设为 UTF-8,可以使用 MySQL 客户端工具 Navicat 来实现。通过执行下面的 SQL 语句创建一个名为 mybatis 的数据库。
CREATE DATABASE mybatis DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
然后再创建一个名为 country 的表并插入一些简单的数据,代码如下。
# 创建数据库
CREATE DATABASE mybatis2 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
# 创建表
CREATE TABLE country (
id INT NOT NULL AUTO_INCREMENT,
countryname VARCHAR(255) NULL ,
countrycode VARCHAR(255) NULL ,
PRIMARY KEY (id)
);
# 初始化表数据
INSERT country(countryname, countrycode) VALUES ('中国','CN'),('美国','US'),('俄罗斯','RU'),('英国','GB'),('法国','FR');
准备好表和简单的数据后,继续来配置 MyBatis。
配置MyBatis
配置 MyBatis 有多种方式,本节使用最基础最常用的 XML 形式进行配置。
除 XML 方式外,在后面介绍和 Spring 集成的时候还会使用 Spring bean 方式进行配置,另外还可以通过 Java 编码方式进行配置。由于 Java 编码配置方式不常用,因此在本书中没有涉及。 |
使用 XML 形式进行配置,首先在 src/main/resources 下面创建 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>
<settings>
<setting name="logImpl" value="LOG4J2"/>
</settings>
<typeAliases>
<package name="com.zccoder.mybatis2.ch1.start.model"/>
</typeAliases>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis2?characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/zccoder/mybatis2/ch1/start/mapper/CountryMapper.xml"/>
</mappers>
</configuration>
简单讲解一下这个配置。
-
<settings> 中的 logImpl 属性配置指定使用 LOG4J 输出日志。
-
<typeAliases> 元素下面配置了一个包的别名,通常确定一个类的时候需要使用类的全限定名称,例如 tk.mybatis.simple.model.Country。在 MyBatis 中需要频繁用到类的全限定名称,为了方便使用,我们配置了 tk.mybatis.simple.model 包,这样配置后,在使用类的时候不需要写包名的部分,只使用 Country 即可。
-
<environments> 环境配置中主要配置了数据库连接,数据库的 url 为 jdbc:mysql://localhost:3306/mybatis,使用的是本机 MySQL 中的 mybatis 数据库,后面的 username 和 password 分别是数据库的用户名和密码(如果你的数据库用户名及密码和这里的不一样,请修改为自己数据库可用的用户名和密码)。
-
<mappers> 中配置了一个包含完整类路径的 CountryMapper.xml,这是一个 MyBatis 的 SQL 语句和映射配置文件,这个 XML 文件会在后面的章节中介绍。
创建实体类和Mapper.xml文件
MyBatis 是一个结果映射框架,这里创建的实体类实际上是一个数据值对象(Data Value Object),在实际应用中,一个表一般会对应一个实体,用于INSERT、UPDATE、DELETE 和简单的 SELECT 操作,所以姑且称这个简单的对象为实体类。
关于 Mapper 的命名方式:在 MyBatis 中,根据 MyBatis 官方的习惯,一般用 Mapper 作为 XML 和接口类名的后缀,这里的 Mapper 和我们常用的 DAO 后缀类似,只是一种习惯而已,本书中全部使用 Mapper 后缀。通常称 XML 为 Mapper.xml 文件,称接口为 Mapper 接口,在实际应用中可以根据自己的需要来定义命名方式。 |
在 src/main/java 下创建一个基础的包 tk.mybatis.simple,在这个包下面再创建 model 包。根据数据库表 country,在 model 包下创建实体类 Country,代码如下。
package com.zccoder.mybatis2.ch1.start.model;
import java.io.Serializable;
public class Country implements Serializable {
private static final long serialVersionUID = -7360153715392794454L;
/**
* 主键
*/
private Long id;
/**
* 国家名称
*/
private String countryname;
/**
* 国家代码
*/
private String countrycode;
@Override
public String toString() {
return "Country{" +
"id=" + id +
", countryname='" + countryname + '\'' +
", countrycode='" + countrycode + '\'' +
'}';
}
/**
* 获取 主键
*
* @return id 主键
*/
public Long getId() {
return this.id;
}
/**
* 设置 主键
*
* @param id 主键
*/
public void setId(Long id) {
this.id = id;
}
/**
* 获取 国家名称
*
* @return countryname 国家名称
*/
public String getCountryname() {
return this.countryname;
}
/**
* 设置 国家名称
*
* @param countryname 国家名称
*/
public void setCountryname(String countryname) {
this.countryname = countryname;
}
/**
* 获取 国家代码
*
* @return countrycode 国家代码
*/
public String getCountrycode() {
return this.countrycode;
}
/**
* 设置 国家代码
*
* @param countrycode 国家代码
*/
public void setCountrycode(String countrycode) {
this.countrycode = countrycode;
}
}
在 src/main/resources 下面创建 tk/mybatis/simple/mapper 目录,再在该目录下面创建 CountryMapper.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.zccoder.mybatis2.ch1.start.mapper.CountryMapper">
<select id="listAll" resultType="Country">
SELECT
id,
countryname,
countrycode
FROM country
</select>
</mapper>
SQL 定义在 CountryMapper.xml 文件中,里面的配置作用如下。
-
<mapper>:XML 的根元素,属性 namespace 定义了当前 XML 的命名空间。
-
<select>元素:我们所定义的一个 SELECT 查询。
-
id属性:定义了当前 SELECT 查询的唯一一个id。
-
resultType:定义了当前查询的返回值类型,此处就是指实体类 Country,前面配置中提到的别名主要用于这里,如果没有设置别名,此处就需要写成 resultType="tk.mybatis.simple.model.Country"。
-
select id,…:查询 SQL 语句。
创建好实体和 Mapper.xml 后,接下来要有针对性地配置 Log4j,让 MyBatis 在执行数据库操作的时候可以将执行的 SQL 和其他信息输出到控制台。
配置Log4j以便查看MyBatis操作数据库的过程
在 src/main/resources 中添加 log4j2.xml 配置文件,输入如下内容。
<?xml version="1.0" encoding="UTF-8"?>
<!-- status:log4j内部console日志级别,monitorInterval:自动更新配置(单位:秒) -->
<configuration status="error" monitorInterval="3600">
<!--自定义一些常量,之后使用${变量名}引用-->
<properties>
<Property name="baseDir">./</Property>
</properties>
<!--appender:定义输出内容,输出格式,输出方式,日志保存策略等,常用其下三种标签[console,File,RollingRandomAccessFile]-->
<!--Appender可以理解为日志的输出目的地-->
<appenders>
<!-- 标准console输出 -->
<Console name="stdOut" target="SYSTEM_OUT">
<PatternLayout pattern="%c{1} %d{yyyy-MM-dd HH:mm:ss SSS} [%t] %T %-5p %m%n"/>
</Console>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<Root level="debug">
<AppenderRef ref="stdOut"/>
</Root>
<Logger name="com.zccoder.mybatis2" level="debug" additivity="false">
<AppenderRef ref="stdOut"/>
</Logger>
</loggers>
</configuration>
用过 Log4j 日志组件的人可能都会知道,配置中的 log4j.logger.tk.mybatis.simple.mapper 对应的是 tk.mybatis.simple.mapper 包,但是在这个例子中,Java 目录下并没有这个包名,只在资源目录下有 mapper 目录。 |
在 MyBatis 的日志实现中,所谓的包名实际上是 XML 配置中的 namespace 属性值的一部分。后面章节中介绍结合接口使用的相关内容时,由于 namespace 属性值必须和接口全限定类名相同,因此才会真正对应到 Java 中的包。当使用纯注解方式时,使用的就是纯粹的包名。
MyBatis 日志的最低级别是 TRACE,在这个日志级别下,MyBatis 会输出执行 SQL 过程中的详细信息,这个级别特别适合在开发时使用。
配置好 Log4j 后,接下来就可以编写测试代码让 MyBatis 跑起来了。
编写测试代码让MyBatis跑起来
首先在 src/test/java 中创建 tk.mybatis.simple.mapper 包,然后创建 CountryMapperTest 测试类,代码如下。
package com.zccoder.mybatis2.ch1.start.mapper;
import com.zccoder.mybatis2.ch1.start.model.Country;
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.BeforeClass;
import org.junit.Test;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
public class CountryMapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init() {
try {
Reader reader = Resources.getResourceAsReader("mybatis.cfg.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testQueryAll() {
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Country> countryList = sqlSession.selectList("listAll");
this.printCountryList(countryList);
sqlSession.close();
}
private void printCountryList(List<Country> countryList) {
for (Country country : countryList) {
System.out.printf("%-4d%4s%4s\n",country.getId(),country.getCountryname(),country.getCountrycode());
}
}
}
对上面这段代码做一个简单的说明,具体如下。
-
通过 Resources 工具类将 mybatis-config.xml 配置文件读入 Reader。
-
再通过 SqlSessionFactoryBuilder 建造类使用 Reader 创建 SqlSessionFactory 工厂对象。在创建 SqlSessionFactory 对象的过程中,首先解析 mybatis-config.xml 配置文件,读取配置文件中的 mappers 配置后会读取全部的 Mapper.xml 进行具体方法的解析,在这些解析完成后,SqlSessionFactory 就包含了所有的属性配置和执行 SQL 的信息。
-
使用时通过 SqlSessionFactory 工厂对象获取一个 SqlSession。
-
通过 SqlSession 的 selectList 方法查找到 CountryMapper.xml中id="selectAll" 的方法,执行 SQL 查询。
-
MyBatis 底层使用 JDBC 执行 SQL,获得查询结果集 ResultSet 后,根据 resultType 的配置将结果映射为 Country 类型的集合,返回查询结果。
-
这样就得到了最后的查询结果 countryList,简单将结果输出到控制台。
-
最后一定不要忘记关闭 SqlSession,否则会因为连接没有关闭导致数据库连接数过多,造成系统崩溃。
上面的测试代码成功执行后,会输出如下日志。
listAll 2024-05-20 19:39:27 712 [Test worker] 1 DEBUG ==> Preparing: SELECT id, countryname, countrycode FROM country
listAll 2024-05-20 19:39:27 745 [Test worker] 1 DEBUG ==> Parameters:
listAll 2024-05-20 19:39:27 775 [Test worker] 1 TRACE <== Columns: id, countryname, countrycode
listAll 2024-05-20 19:39:27 775 [Test worker] 1 TRACE <== Row: 1, 中国, CN
listAll 2024-05-20 19:39:27 779 [Test worker] 1 TRACE <== Row: 2, 美国, US
listAll 2024-05-20 19:39:27 779 [Test worker] 1 TRACE <== Row: 3, 俄罗斯, RU
listAll 2024-05-20 19:39:27 780 [Test worker] 1 TRACE <== Row: 4, 英国, GB
listAll 2024-05-20 19:39:27 780 [Test worker] 1 TRACE <== Row: 5, 法国, FR
listAll 2024-05-20 19:39:27 781 [Test worker] 1 DEBUG <== Total: 5
1 中国 CN
2 美国 US
3 俄罗斯 RU
4 英国 GB
5 法国 FR
从日志中可以看到完整的 SQL 输出和结果输出,从日志对应的级别可以发现 SQL、参数、结果数都是 DEBUG 级别,具体的查询结果列和数据都是 TRACE 级别。
通过一系列的操作,我们让一个简单的 MyBatis 例子跑了起来,相信大家现在对 MyBatis 已经有了初步的了解。
simple 项目下载地址:http://mybatis.tk/book/simple-start.zip。 在学习这部分代码时,如果程序无法运行,或者不知道这些配置和测试类该写到哪里,都可以从该网址下载这部分的完整代码,通过对比来解决问题,或者直接使用这部分基础代码来继续学习接下来的内容。 |