MyBatis入门

MyBatis简介

Mybatis与Hibernate都是持久层框架,这类框架的作用就是将数据库中的表和POJO映射起来,它们的本质就是Java对数据库的操作的抽象,所以我们也将这种框架称为对象关系映射框架(ORM,Object Relational Mapping)。它们的区别也很明显,Hibernate基本不需要编写SQL,它可以根据映射规则自动生成SQL语句,是一种全表映射。而MyBatis不屏蔽SQL,我们可以自己定制SQL,这样就提供给了我们足够的灵活性与优化的可能。总而言之,MyBatis相对于Hibernate来说具有性能高,响应快,开发灵活的特点。

MyBatis组件

MyBatis的核心组件分为4个部分:

  • SqlSessionFactoryBuilder(构造器):它会根据mybatis的配置文件(Configuration配置类)来生成SqlSessionFactory,这里采用的是分步构建的Builder模式
  • SqlSessionFactory(工厂):用于生成SqlSession,可以被认为是数据库连接池
  • SqlSession(会话):既可以直接发送SQL执行并返回结果,也可以获取映射器Mapper接口(动态代理的类)执行SQL得到返回结果,相当于数据库连接(Connection对象)
  • Mapper(映射器):由一个Java接口和XML文件构成:接口用于给出方法的入参以及返回值,XML给出SQL语句和映射规则。映射器的主要作用就是将SQL查询到的结果映射为一个POJO,或者将POJO的数据插入到数据库中

注意,无论是映射器还是SqlSession都可以发送SQL到数据库执行,但是为了保证代码的可读性与可维护性,推荐使用Mapper接口编程来完成该操作。

如何使用MyBatis

首先,在MyBatis中有两种XML配置文件,一种是基础配置文件,它只有一个,用于配置一些MyBatis的上下文参数和运行环境;另一种是映射器的XML映射文件,它可以配置映射关系,SQL等等。简单来说,在使用MyBatis的时候,先给出MyBatis的配置文件用于生成SqlSession,然后再给出映射器Mapper的接口与相应的映射XML文件,最后就可以生成Mapper接口的动态代理类来发送SQL获取结果了。

spring-mybatis

MyBatis框架上手很快,使用起来也很简单。MyBatis通常是在Spring容器中配置使用,Spring也对MyBatis提供了支持,接下来看一个在Spring中使用MyBatis的例子:

该项目使用maven构建,IDEA中的工程结构如图:

所有的xml配置文件都放置在main目录下的resources中,所有的java代码都在main目录下的java文件中。

在开发之前,需要做一些准备工作,在本地的mysql数据库中新建数据表t_person:

建完数据表之后数据表结构如图:

然后,我们需要在maven的pom文件中导入相关的依赖包,在搭建SpringMVC+Spring+MyBatis项目的时候,很多问题都出现在pom文件中的依赖中,要不是导入包少了,要不是导入的包与包之间版本问题,所以要多加小心:

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<dependencies>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--以下3个为spring的基础设施-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mybatis-spring spring对mybatis的支持 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- dbcp2数据库连接池-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
<!-- mysql的连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
</dependencies>

在导入以上依赖之后,我们就可以进行开发了。首先要完成的就是mybatis的全局配置文件,在resources目录下的mybatis-config.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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>
<mappers>
<mapper resource="PersonMapper.xml"/>
</mappers>
</configuration>

我们只配置了mybatis的日志是使用log4j来完成,log4j的属性文件在resources目录下,我们可以自行修改log4j的日志级别,为了更加详细了解过程,这次使用了DEBUG级别输出到控制台,另外还配置了映射器的映射文件。

接下来就来完成映射器,映射器由接口与映射文件构成,先来看看PersonMapper接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package mybatis.spring.test.mapper;
import mybatis.spring.test.pojo.Person;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
/**
* Created by lujunqiu on 2018/1/23.
*/
@Repository
public interface PersonMapper {
public int insertPerson(Person person);
public Person getPerson(@Param("id") int id);
public int updatePerson(Person person);
public int deletePerson(@Param("id") int id);
}

@Param(“id”)注解用于将函数的入参传入SQL语句,后面的博客会详细介绍入参的绑定与结果的绑定。另外这里的Person类对应于我们事先定义于数据库中的t_person表:

1
2
3
4
5
6
7
8
9
public class Person {
private String name;
private int age;
private String tel;
private int id;
/**getter and setter**/
}

根据映射器接口,再来完成映射文件,位于resources目录下的PersonMapper文件,这是mybatis允许我们自己写SQL与映射规则的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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="mybatis.spring.test.mapper.PersonMapper">
<insert id="insertPerson" useGeneratedKeys="true" keyProperty="id" parameterType="mybatis.spring.test.pojo.Person">
INSERT INTO t_person(name,age,tel) VALUES (#{name},#{age},#{tel})
</insert>
<delete id="deletePerson" parameterType="int">
DELETE FROM t_person WHERE id=#{id}
</delete>
<update id="updatePerson" parameterType="mybatis.spring.test.pojo.Person">
UPDATE t_person set name = #{name},age=#{age},tel=#{tel} WHERE id = #{id}
</update>
<select id="getPerson" parameterType="int" resultType="mybatis.spring.test.pojo.Person">
SELECT name,age,tel,id from t_person WHERE id = #{id}
</select>
</mapper>

mapper namespace表示的是该映射文件对应的接口的全限定包名,后面的SQL标签的id名对应与接口的方法名,注意不要弄错了。

MyBatis在默认情况下提供自动映射,只要SQL中的列名能和POJO对应起来即可。这里的列名name,age,tel,id与POJO中的属性名name,age,tel,id名字对应,所以在SELECT返回结果时Mybatis可以帮助我们完成自动映射。

至此,基本的构件就完成了。既然要在spring中配置mybatis,接下来就在spring容器中配置我们需要的组件,spring容器的配置文件是位于resources目录下的applicationContext.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
<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="666666"/>
</bean>
<!--Mybatis的基本构件SqlSessionFactory-->
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--spring提供给mybatis用于扫描Mapper的工具,通过给Mapper接口标注就可以直接使用该接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--需要扫描的包-->
<property name="basePackage" value="mybatis.spring.test.mapper"/>
<property name="sqlSessionFactoryBeanName" value="SqlSessionFactory"/>
<!--使用@Repository注解标注Mapper-->
<property name="annotationClass" value="org.springframework.stereotype.Repository"/>
</bean>
</beans>

我们使用了spring提供的Mapper扫描工具类,可以将@Repository注解标注的接口动态代理为Mapper,所以我们需要在PersonMapper接口前标注@Repository,这样spring就会将该Mapper加入容器给我们使用。通过这种办法,spring将mybatis中的SqlSession从我们代码中擦除了,就可以直接面向Mapper接口编程。

现在开始测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import mybatis.spring.test.mapper.PersonMapper;
import mybatis.spring.test.pojo.Person;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by lujunqiu on 2018/1/23.
*/
public class test {
public static void main(String[] args) {
Logger logger = Logger.getLogger(test.class);
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonMapper mapper = ctx.getBean(PersonMapper.class);
Person person = new Person();
person.setAge(24);
person.setName("qiu");
person.setTel("13212778355");
mapper.insertPerson(person);
}
}

通过mybatis向mysql数据库插入一条数据,控制台日志输出:

[QC] DEBUG [main] org.mybatis.spring.SqlSessionUtils.getSqlSession(97) | Creating a new SqlSession
[QC] DEBUG [main] org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(87) | JDBC Connection [259564670, URL=jdbc:mysql://localhost:3306/test, UserName=root@localhost, MySQL Connector Java] will not be managed by Spring
[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | ==> Preparing: INSERT INTO t_person(name,age,tel) VALUES (?,?,?)
[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | ==> Parameters: qiu(String), 24(Integer), 13212778355(String)
[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | <== Updates: 1
[QC] DEBUG [main] org.mybatis.spring.SqlSessionUtils.closeSqlSession(191) | Closing non transactional SqlSession
[org.apache.ibatis.session.defaults.DefaultSqlSession@2a5c8d3f]
[QC] DEBUG [main] test.main(20) | 1

通过日志可以看到mybatis执行SQL的过程,我们也可以去mysql中查看结果,同样的方法可以测试其他方法。

总结

以上介绍了MyBatis的基本组件以及一个利用自动映射的且只涉及简单的增,删,改,查的实例,后续将会详细介绍MyBatis的映射器等其他内容,方便我们使用MyBatis完成更加复杂的业务需求。

0%