引言

当我们想操作数据库的时候,有多种选择,比如上一篇文章用的JDBC,或者Spring的JdbcTemplate,或者Hibernate,在就是MyBatis。
Mybatis是一种半自动ORM框架,需要手动维护SQL,一般是xml文件,优点就是好控制,缺点就是维护的数据多。项目中现在使用springboot+tk-Mybatis,使用起来很方便,对用户屏蔽内部实现,但是对于学习来说,还是使用最基础的配置,能够更好的理解。

1、Spring+Mybatis例子准备

这里简单的写个Spring+Mybatis的小例子跑起来,之后分析:

1.1、test库:

1
2
3
4
CREATE TABLE `people` (
`id` int(11) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

1.2、entity:

1
2
3
4
5
6
7
import lombok.Data;

@Data
public class PeopleEntity {
private int id;
private String name;
}

1.3、mapper.java:

1
2
3
public interface PeopleMapper {
List<PeopleEntity> query();
}

1.4、mapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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.demo.mybatis.mapper.PeopleMapper">
<resultMap id="BaseResultMap" type="com.demo.mybatis.entity.PeopleEntity">
<result column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
</resultMap>

<select id="query" resultMap="BaseResultMap">
SELECT id,name from people
</select>

</mapper>

1.5、因为我是以springboot2.0的架子学习,所以引入pom:

1
2
3
4
5
6
7
8
9
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

mybatis相关的包.png

上面为准备阶段,下面通过两种方式使用MyBatis。

2、两种方式使用mybatis

2.1、springboot默认配置实现

2.1.1、application.properties

1
2
3
4
5
6
mybatis.type-aliases-package=com.demo.mybatis.entity
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
mybatis.mapper-locations=classpath:mapper/*.xml

2.1.2、Application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@SpringBootApplication
@MapperScan("com.demo.mybatis.mapper")
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext confApp = null;
try {
confApp = SpringApplication.run(Application.class, args);
} finally {
close(confApp);
}
}
private static void close(ConfigurableApplicationContext confApp) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
if (confApp != null) {
confApp.close();
}
}
});
}
}

2.1.3、AppApplicationTests

1
2
3
4
5
6
7
8
9
10
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppApplicationTests {
@Autowired
private PeopleMapper peopleMapper;
@Test
public void test() {
System.out.println(JSONObject.toJSONString(peopleMapper.query()));
}
}

2.1.4、结果

1
2
3
4
5
6
com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
[{"id":1,"name":"李四"}]
o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.

顺利读取出结果,这里HikariDataSource为数据库连接池,springboot2.0默认连接池,看了一下它的介绍,感觉确实不错,有时间会研究一下为啥它那么快。

接下来换一种方式实现上面的功能:

2.2、xml配置文件实现

首先注释掉application.properties中相关配置:

1
2
3
4
5
6
#mybatis.type-aliases-package=com.demo.mybatis.entity
#spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/test
#spring.datasource.username=root
#spring.datasource.password=123456
#mybatis.mapper-locations=classpath:mapper/*.xml

之后注视掉Application的MapperScan注解:

1
2
3
4
5
@SpringBootApplication
//@MapperScan("com.demo.mybatis.mapper")
public class Application {
...
}

接下来就是重点了:

2.2.1、新增jdbc.properties
1
2
3
4
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456
2.2.2、mybatis-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
<?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="cacheEnabled" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="People" type="com.demo.mybatis.entity.PeopleEntity"/>
</typeAliases>
</configuration>
2.2.3、spring-mybatis.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

<context:property-placeholder location="classpath:jdbc.properties"/>

<!-- 配置数据源 -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<!-- 配置 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置 mybatis-config.xml 路径 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 给 SqlSessionFactory 配置数据源,这里引用上面的数据源配置 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置 SQL 映射文件 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

<!-- 配置 MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 配置 Dao 接口所在的包 -->
<property name="basePackage" value="com.demo.mybatis.mapper"/>
</bean>
</beans>

这里也使用HikariDataSource数据源。

2.2.4、AppApplicationTests
1
2
3
4
5
6
7
8
9
10
11
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration("classpath:spring-mybatis.xml")
public class AppApplicationTests {
@Autowired
private PeopleMapper peopleMapper;
@Test
public void test() {
System.out.println(JSONObject.toJSONString(peopleMapper.query()));
}
}

比以前增加了@ContextConfiguration(“classpath:spring-mybatis.xml”),扫描配置文件生成bean。

2.2.5、结果
1
2
3
4
5
6
com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
[{"id":1,"name":"李四"}]
o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.

发现结果和用注解的一样。但是发现用springboot默认确实省去了使用者的很多工作量,但是为了便于学习,我这分析的时候采用配置文件的方式,这中理解起来可能会更好一点。

之后要分析配置文件的读取,即有两个大方面的内容:

  • MyBatis配置最终解析成什么样了?
  • MyBatis是怎么样和Spring结合的,为什么可以直接注入进来Mapper?

tencent.jpg