MyBatis学习笔记(一)简单配置让MyBatis跑起来
- 2020 年 4 月 3 日
- 筆記
MyBatis
是一款优秀的支持自定义SQL
查询、存储过程和高级映射的持久层框架,消除了几乎多有的JDBC
代码和参数的手动设置和结果集的检索。MyBatis
可以使用XML
和注解进行配置和映射,MyBatis
通过将参数映射到配置的SQL
形成最终执行的SQL
语句,最后将执行SQL
的结果映射成Java
对象返回。
一、创建Maven项目
Maven
是一个优秀的项目构建和管理工具,使用Maven
构建项目非常方便,可以非常方便地处理Jar
包依赖问题。这里提供构建MyBatis
应用的的pom.xm
l配置内容。
<?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.lemon</groupId> <artifactId>lemon-mybatis</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <mybatis.version>3.4.6</mybatis.version> <junit.version>4.12</junit.version> <mysql.connector.version>8.0.11</mysql.connector.version> <slf4j.version>1.7.25</slf4j.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.20</lombok.version> </properties> <dependencies> <!-- mybatis核心依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- 测试依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- mysql数据库连接依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.connector.version}</version> </dependency> <!-- 日志模块 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> </project>
其中<properties>
标签指定了源代码的编码方式为UTF-8
,以及项目所依赖的Jar
包的版本。除了引入MyBatis
应用所必须的Jar
以外,还引入了lombok
,lombok
是一款非常优秀的插件,它可以被安装到Eclipse
和IntelliJ IDEA
上,使用lombok
的相关注解可以使得创建JavaBean
的代码十分简洁,至于如何使用,可以去CSDN
上找到相关博客学习一下。
二、准备数据库
这里准备一个非常简单的MySQL
数据库,数据库的编码方式设置为UTF-8
,现在提供相关的SQL
语句来建立数据库并插入测试数据。
-- 创建名称为lemon-mybatis的数据库 CREATE DATABASE lemon-mybatis DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; -- 使用数据库 use lemon-mybatis; -- 创建数据库表并插入数据 DROP TABLE IF EXISTS `country`; CREATE TABLE `country` ( `id` int(11) NOT NULL AUTO_INCREMENT, `countryName` varchar(255) DEFAULT NULL, `countryCode` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ); INSERT `country` (`countryName`, `countryCode`) VALUES ('中国', 'CN'), ('美国', 'US'), ('俄罗斯', 'RU'), ('英国', 'GB'), ('法国', 'FR');
三、配置MyBatis
配置MyBatis
的方式有多种,最常见的是使用XML
形式进行配置,当然,与Spring
进行整合的时候,也可以使用Spring Bean
的方式进行配置,另外还可以通过Java
编码方式进行配置,但是这种方式不常用,这里仅仅使用XML
形式配置MyBatis
。 在项目的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="LOG4J"/> </settings> <!-- 配置实体类包名 --> <typeAliases> <package name="com.lemon.example.model"/> </typeAliases> <environments default="development"> <environment id="development"> <!-- 配置默认事务管理器 --> <transactionManager type="JDBC"> <property name="" value=""/> </transactionManager> <dataSource type="UNPOOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.171.133:3306/lemon-mybatis?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!-- 当没有写Mapper对应的接口时候,需要在这里配置XML文件位置,且标签mapper必须有在package前面 --> <mapper resource="com/lemon/example/mapper/CountryMapper.xml"/> </mappers> </configuration>
简单介绍一下这个配置文件:
-
<settings>
中的logImpl
属性配置指定使用LOG4J
输出日志 -
<typeAliases>
配置了一个包的别名,通常情况下,辨别一个类使用的是类的全限定名称,比如com.lemon.example.model.Country
,在Mybatis
中会频繁使用到类的全限定名称,所以配置包的别名以后,在配置文件中需要使用到全限定名称的时候直接写简单的类名即可,如Country
。 -
<environments>
环境配置中主要配置了数据库连接,可以同时配置多个数据库连接环境,内部使用<environment>
隔离不同的环境。 -
<mappers>
标签是配置配置Mapper
文件的标签,其内部可以配置多个多个类似CountryMapper.xml
,使用的是<mapper>
标签,也可以使用<package>
标签,更加便捷,后面会介绍更多细节。
四、创建实体类和Mapper.xml文件
MyBatis
是一个结果映射型框架,一般在数据库设计和实体类设计的过程中,都是一个表对应一个实体类,对数据库的增删改查一般都是将实体类作为数据载体。而这里的Mapper.xml
文件,是SQL
语句和结果映射的基本载体,一般的命名习惯是实体类的名称加上Mapper
,比如CountryMapper.xml
。在实际的开发过程中,一个实体类Country
对应一个接口CountryMapper.java
和CountryMapper.xml
文件,其中接口CountryMapper.java
放在src/main
下面的包里,比如com.lemon.example.mapper
,而CountryMapper.xml
文件则放在src/main/resources
文件夹下,建立的各层文件夹和对应的接口包名一致,如com/lemon/example/mapper
,其中接口并不是必须的。 本例中实体类Country
的代码为:
package com.lemon.example.model; import lombok.Data; /** * @author lemon * @date 2018/4/22 下午9:32 */ @Data public class Country { private Long id; private String countryName; private String countryCode; }
这里导入了lombok
的Data
注解,在运行时会自动为实体类创建getter
和setter
方法。本例中没有创建CountryMapper
接口,所以直接创建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.lemon.example.mapper.CountryMapper"> <select id="selectAll" resultType="Country"> select id, countryName, countryCode from country </select> </mapper>
对于上面的Mapper
文件,进行如下解释:
- 标签
<mapper>
是XML
的根元素,属性namespace
定义了当前XML
的命名空间,是唯一的,如果没有创建该Mapper
文件的Mapper
接口,那么这个命名空间可以随意设置,如果创建了接口,那么这个命名空间的值必须是对应接口的全限定类名。 - 标签
<select>
是定义查询的语句的标签,它的属性id
是该标签的标识,是唯一的,如果该Mapper
文件有对应的接口,那么id
是对应接口的方法名称,属性resultType
是描述查询结果映射到哪个实体类中,由于在mybatis-config.xml
文件中配置了别名,所以这里仅仅需要写Country
(不区分大小写,但是为了统一,建议和类名一致)即可,否则将需要写全限定类名com.lemon.example.model.Country
。
五、配置Log4j日志文件
对于项目的开发,一看都要量身定制日志文件,以便调优,这里将在src/main/resources
文件夹下建立log4j.properties
文件,代码如下:
# 全局配置 log4j.rootLogger=ERROR, stdout # Mybatis日志配置 log4j.logger.com.lemon.example.mapper=TRACE # 控制台输出配置 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
日志的全局配置是Error
级别的,设置的是控制台输出,这是最简单的设置,也是开发阶段比较实用的设置。Mybatis
日志配置指定了包名com.lemon.example.mapper
,它对应的是接口,TRACE
是最低级别的日志,这可以使得SQL
语句执行的信息也会被打印出来。控制台输出配置了控制台日志打印的基本格式。
六、编写测试代码
本篇文章是一个入门案例,介绍了Mybatis
最基本的配置,接下来编写一个测试代码,看看代码的运行效果。测试代码一般在Maven
项目中都是写在src/test/java
下的包中的,建立包com.lemon.example.mapper
,并在该包下创建基础测试类BaseMapperTest
,代码如下:
package com.lemon.example.mapper; 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 java.io.IOException; import java.io.Reader; /** * 测试基础类 * * @author lemon * @date 2018/5/20 下午11:37 */ public class BaseMapperTest { private static SqlSessionFactory sqlSessionFactory; @BeforeClass public static void init() { try { Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); reader.close(); } catch (IOException e) { e.printStackTrace(); } } public SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
这是一个基础类,主要负责加载mybatis-config.xml
来创建SqlSession
实例对象,因为后期会有很多测试,如果每个测试都要重复编写获取SqlSession
实例对象的代码,就显得有些多余了,这里进行了基本的代码重构复用。对于CountryMapper
的测试,代码如下:
package com.lemon.example.mapper; import com.lemon.example.model.Country; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; /** * @author lemon * @date 2018/5/8 下午5:22 */ public class CountryMapperTest extends BaseMapperTest { @Test public void testSelectAll() { try (SqlSession sqlSession = getSqlSession()) { List<Country> countryList = sqlSession.selectList("com.lemon.example.mapper.CountryMapper.selectAll"); printCountryList(countryList); } } private void printCountryList(List<Country> countryList) { for (Country country : countryList) { System.out.printf("%-4d%4s%4sn", country.getId(), country.getCountryName(), country.getCountryCode()); } } }
对上面两段代码进行如下解释:
- 通过
Resources
工具类将mybatis-config.xml
配置读入Reader
。 - 再通过
SqlSessionFactoryBuilder
建造类使用Reader
创建SqlSessionFactory
工厂对象,在创建SqlSessionFactory
工厂对象过程中,首先会解析mybatis-config.xml
配置文件,解析完成之后,SqlSessionFactory
工厂对象就包含了所有的属性配置和执行SQL
的信息。 - 通过继承
BaseMapperTest
类,直接调用父类的getSqlSession
方法可以直接获取SqlSession
对象。 - 通过
SqlSession的selectList
方法查找到CountryMapper.xml
中id="selectAll"
方法,执行SQL
语句,MyBatis
底层使用JDBC
执行SQL
语句,并将查询到的结果集ResultSet
后,根据resultType
的配置将结果映射到Country
类型的集合中,返回查询结果。 - 最后将查询到的结果按照指定的格式进行输出到控制台。记得要关闭
SqlSession
,常见的做法是将其写在finally
块中,但是代码中使用的是JDK1.7
的新特性,直接写在try
后面的圆括号里面,资源在利用完毕之后会自动关闭,这样做代码更加简洁。
执行测试代码,输出的日志如下所示:
DEBUG [main] - ==> Preparing: select id, countryName, countryCode from country DEBUG [main] - ==> Parameters: TRACE [main] - <== Columns: id, countryName, countryCode TRACE [main] - <== Row: 1, 中国, CN TRACE [main] - <== Row: 2, 美国, US TRACE [main] - <== Row: 3, 俄罗斯, RU TRACE [main] - <== Row: 4, 英国, GB TRACE [main] - <== Row: 5, 法国, FR DEBUG [main] - <== Total: 5 1 中国 CN 2 美国 US 3 俄罗斯 RU 4 英国 GB 5 法国 FR
这篇博文仅仅是对Mybatis
进行了一个简单的案例实战,后面会继续发布多篇Mybatis
的学习笔记,欢迎阅读,我们共同进步。