1 MyBatis简介
1.1 什么是MyBatis
-
MyBatis 是一款优秀的持久层框架,半自动ORM
-
它支持自定义 SQL、存储过程以及高级映射,MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作,MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
-
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github
1.2 为什么要学MyBatis
-
简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
-
灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
-
解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
-
提供映射标签,支持对象与数据库的orm字段关系映射
-
提供对象关系映射标签,支持对象关系组建维护
-
提供xml标签,支持编写动态sql
-
跟JDBC相比使用方便,跟Hibernate相比首先是学习成本低(方法,缓存)
2 MyBatis入门
2.1 MyBatis的开发步骤
MyBatis图标需要下载插件MyBatisX,lombok也需要下载插件(File --> Settings --> Plugins)
-
搭建环境、导包
-
编写MyBatis核心配置文件(configuration.xml)
-
编写代码
-
测试
2.2 搭建环境
新建module,导入maven
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!--
资源插件 告诉maven把 src/main/java目录中的 指定扩展名的文件 拷贝到 target/classes目录中。
-->
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes>
<!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<!-- filtering 选项 false 不启用过滤器, *.property 已经起到过
滤的作用了 -->
<filtering>false</filtering>
</resource>
</resources>
</build>
2.3 编写核心配置文件(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>
<!-- 读取db.properties文件的内容 -->
<properties resource="db.properties">
<!-- 如果properties中有跟name相同的属性,以文件为准 -->
<property name="password" value="123456"/>
</properties>
<!-- 在控制台显示执行的sql语句 -->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 给参数设置别名,就不用写全量限定名称 -->
<typeAliases>
<package name="cn.blb.mybatis01.pojo"/>
</typeAliases>
<!-- 环境 可以多套 default 选择环境id-->
<environments default="development">
<environment id="development">
<!-- 事务 - 默认JDBC -->
<transactionManager type="JDBC"/>
<!-- 数据源 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!-- 映射,作用就是将接口跟实现类进行注册 -->
<mappers>
<mapper resource="cn/blb/demo02/mapper/mapper.xml"/>
</mappers>
</configuration>
2.4 db.properties数据库连接文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///person?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=root
2.5 编写代码
- 实体类
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Staff {
private int id;
private String name;
private int age;
private String address;
}
- Dao接口
public interface StaffDao {
// 查询所有
List<Staff> selectAll();
// 添加
int insertStall(Staff staff);
// 删除
int deleteStall(int id);
// 修改
int updateStall(Staff staff);
}
- 接口实现类
<?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">
<!-- namespace 相当于是实现interface,相当于implements -->
<mapper namespace="cn.blb.demo02.dao.StaffDao">
<!--
id = 实现的方法名
resultType = 返回值类型
-->
<!--查询所有-->
<select id="selectAll" resultType="cn.blb.demo02.pojo.Staff">
select * from staff;
</select>
<!--添加-->
<insert id="insertStall">
insert into staff value(#{id},#{name},#{age},#{address})
</insert>
<!--删除-->
<delete id="deleteStall">
delete from staff where id = #{id}
</delete>
<!--修改-->
<update id="updateStall">
update staff set name = #{name},age = #{age},address = #{address} where id = #{id}
</update>
</mapper>
- 编写测试类
public class test01 {
SqlSessionFactory sqlSessionFactory;
@Before
public void beforeTest() throws IOException {
// 相对路径,相对的是resources下的资源
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void selectAll(){
// sqlSerssion 相当于statement对象,用于操作数据库
SqlSession sqlSession = sqlSessionFactory.openSession();
// 获取mapper对象 接口的类型
StaffDao staffDao = sqlSession.getMapper(StaffDao.class);
List<Staff> list = staffDao.selectAll();
list.forEach(System.out::println);
}
@Test
public void insertStaff(){
SqlSession sqlSession = sqlSessionFactory.openSession();
StaffDao staffDao = sqlSession.getMapper(StaffDao.class);
Staff staff = new Staff();
staff.setName("路人甲");
staff.setAge(28);
staff.setAddress("南昌");
int i = staffDao.insertStall(staff);
// 手动提交事务 - 新增、删除。修改才需要
sqlSession.commit();
System.out.println("i = " + i);
}
@Test
public void deleteStaff(){
SqlSession sqlSession = sqlSessionFactory.openSession();
StaffDao staffDao = sqlSession.getMapper(StaffDao.class);
int i = staffDao.deleteStall(5);
// 手动提交事务 - 新增、删除。修改才需要
sqlSession.commit();
System.out.println("i = " + i);
}
@Test
public void updateStall(){
SqlSession sqlSession = sqlSessionFactory.openSession();
StaffDao staffDao = sqlSession.getMapper(StaffDao.class);
Staff staff = new Staff();
staff.setId(3);
staff.setName("王五五");
staff.setAge(25);
staff.setAddress("北京");
int i = staffDao.updateStall(staff);
// 手动提交事务 - 新增、删除。修改才需要
sqlSession.commit();
System.out.println("i = " + i);
}
}
3 配置解析
3.1 核心配置文件
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
-
properties(属性)
-
settings(设置)
-
typeAliases(类型别名)
-
typeHandlers(类型处理器)
-
objectFactory(对象工厂)
-
plugins(插件)
-
environments(环境配置)
-
environment(环境变量)
-
transactionManager(事务管理器)
-
dataSource(数据源)
-
-
-
databaseIdProvider(数据库厂商标识)
-
mappers(映射器)
3.2 环境配置 environments
MyBatis 可以配置成适应多种环境
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境
注意一些关键点:
-
默认使用的环境 ID(比如:default="development")
-
每个 environment 元素定义的环境 ID(比如:id="development")
-
事务管理器的配置(比如:type="JDBC")
-
数据源的配置(比如:type="POOLED")
3.2.1 事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
-
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
-
MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。例如:
<transactionManager type="MANAGED">
<property name="closeConnection" value="false"/>
</transactionManager>
3.2.2 属性 properties
我们可以通过properties属性来实现引用配置文件
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。【db.properties】
-
编写db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql:///staff?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=root
-
在核心配置文件中引入
<!--引用外部配置文件--> <properties resource="db.properties"> <property name="username" value="root"/> <property name="password" value="123456"/> </properties>
-
可以直接引入外部文件
-
可以在其中增加一些属性配置
-
如果两个文件有同一个字段,优先使用外部配置文件的
-
3.3 映射器 mappers
MapperRegistry:注册绑定我们的Mapper文件;
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!--
使用映射器接口实现类的完全限定类名
接口和他的Mapper配置文件必须同名
接口和他的Mapper配置文件必须在同一个包下
-->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
3.4 类型别名 typeAliases
-
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置
-
意在降低冗余的全限定类名书写
<!--可以给实体类起别名-->
<typeAliases>
<typeAlias type="cn.blb.pojo.User" alias="person"/>
</typeAliases>
- 也可以指定一个包,每一个在包
domain.blog
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如domain.blog.Author
的别名为author
,;若有注解,则别名为其注解值。见下面的例子:
<typeAliases>
<package name="cn.blb.pojo"/>
</typeAliases>
@Alias("author")
public class Author {
...
}
3.5 设置 Settings
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存 | true~false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态 | true~false | false |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn | true~false | false |
一个配置完整的 settings 元素的示例如下
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>