MyBatis
简介(来自维基百科)
功能概况
MyBatis入门
使用JDBC操作数据库的弊端
- 数据库连接资源的创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
- SQL语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
- 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
- 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
MyBatis的架构
MyBatis配置
- SqlMapConfig.xml,此文件作为MyBatis的全局配置文件,配置了mybatis的运行环境等信息
- mapper.xml文件即SQL映射文件,文件中配置了操作数据库的SQL语句。此文件需要在SqlMapConfig.xml中加载
- 通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
- 由会话工厂创建SqlSession即会话,操作数据库需要通过SqlSession进行
- MyBatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器
- Mapped Statement也是MyBatis一个底层封装对象,它包装了MyBatis配置信息及SQL映射信息等,mapper.xml文件中一个SQL对应一个Mapped Statement对象,SQL的id即是Mapped Statement的id
- Mapped Statement对SQL执行输入参数进行定义,包括HashMap、基本类型、POJO,Executor通过Mapped Statement在执行SQL前将输入的java对象映射至SQL中,输入参数映射就是JDBC编程中对PreparedStatement设置参数
- Mapped Statement对SQL执行输出结果进行定义,包括HashMap、基本类型、POJO,Executor通过Mapped Statement在执行SQL后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程
快速入门
环境搭建
- 创建项目,导入依赖jar包
- 加入核心配置文件和log4j的配置文件
- 创建POJO
- 创建SQL映射文件
- 加载映射文件
- 在核心配置文件中加载映射文件
导入依赖jar包
创建资源文件夹并在其中创建配置文件(log4j.properties和SqlMapConfig.xml文件)
加入log4j.properties
# Global logging configuration log4j.rootLogger=DEBUG, stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
MyBatis默认使用log4j作为输出日志工具
<?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> <!-- 和spring整合后 environments配置将废除 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="root" /> </dataSource> </environment> </environments> </configuration>
SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理
创建POJO
创建SQL映射文件
<?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:命名空间,用于隔离sql,还有一个很重要的作用 --> <mapper namespace="test"> </mapper>
在SqlMapConfig文件中引入SQL映射文件
创建测试类测试环境搭建情况
往User.xml中添加SQL语句
测试根据id查询单个User
package com.zella.test; import com.zella.mybatis.pojo.User; 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.Test; import java.io.InputStream; public class MyBatisTest { @Test public void testMyBatis() throws Exception { // 加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); // 创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); // 创建SqlSession SqlSession session = sqlSessionFactory.openSession(); // 执行SQL语句 User user = session.selectOne("test.findUserById", 10); System.out.println(user); } }
测试根据用户名模糊查询对应用户列表
测试插入数据
测试插入用户后返回id
测试更新用户
测试删除用户
使用MyBatis解决了JDBC操作数据库的弊端
- 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题
- 解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接
- SQL语句写在代码中造成代码不易维护,实际应用SQL变化的可能较大,SQL变动需要改变Java代码
- 解决:将SQL语句配置在XXXXmapper.xml文件中与Java代码分离
- 向SQL语句传参数麻烦,因为SQL语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应
- 解决:MyBatis自动将Java对象映射至SQL语句,通过statement中的parameterType定义输入参数的类型
- 对结果集解析麻烦,SQL变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成POJO对象解析比较方便
- 解决:MyBatis自动将SQL执行结果映射至Java对象,通过statement中的resultType定义输出结果的类型
*MyBatis和Hibernate的不同
使用MyBatis开发Dao层
- 原始/传统Dao开发方法
- Mapper动态代理开发方法
MyBatis的主要API的使用范围
- SqlSession中封装了对数据库的操作,如:查询、插入、更新、删除等
- SqlSession通过SqlSessionFactory创建
- SqlSessionFactory是通过SqlSessionFactoryBuilder进行创建
SqlSessionFactoryBuilder
- SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory创建的
- 所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量
SqlSessionFactory
- SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory
SqlSession
- SqlSession是一个面向用户的接口,sqlSession中定义了数据库操作方法
- 每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的
- 因此最佳的范围是请求或方法范围,绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中
- 每打开一个SqlSession使用完毕就要关闭它,通常把这个关闭操作放到finally块中以确保每次都能执行关闭
传统Dao开发方法
步骤
- 编写映射文件
- 编写Dao接口
- 编写Dao接口实现类
- 测试
原始Dao开发方法存在的问题
- Dao方法体存在重复代码:通过SqlSessionFactory创建SqlSession,调用SqlSession的数据库操作方法
- 调用SqlSession的数据库操作方法(如selectOne("xxx.xxx",id))需要指定statement的id,这里存在硬编码,不得于开发维护
Mapper动态代理方式开发Dao
Mapper接口开发需要遵循以下规范
测试
两个小细节
selectOne和selectList
- 如果返回list则调用selectList方法
- 如果返回单个对象则调用selectOne方法
namespace
SqlMapConfig.xml配置文件
SqlMapConfig文件的标签(配置内容)
- properties(属性)
- settings(全局配置参数)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境集合属性对象)
- environment(环境子属性对象)
- transactionManager(事务管理)
- dataSource(数据源)
- environment(环境子属性对象)
- mappers(映射器)
properties(属性)
- 在properties元素体内定义的属性首先被读取。
- 然后会读取properties元素中resource或url对应的properties文件加载的属性,它会覆盖已读取的同名属性
typeAliases(类型别名)
MyBatis默认支持的别名
别名 | 映射的类型 |
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
自定义别名
- 别名大小写不敏感
- 批量定义别名只需要定义父包,将扫描父包下所有类,包括子包内
- 但最好保证这个父包下所有类都是POJO
mappers(映射器)
<mapper resource=""/>
<mapper class=""/>
<package name=""/>(常用)
<mapper url=""/>
MyBatis深入
输入映射和输出映射
输入映射-parameterType
传递简单类型
传递POJO
传递POJO包装对象
输出映射-resultType
简单输出类型
输出POJO
输出POJO列表
输出resultMap类型
动态SQL
静态的SQL的弊端
where标签
SQL片段
foreach标签
注意
关联查询
一对一查询
方式一 创建新的POJO并使用resultType来作为输出类型
方式二
一对多查询
*总结resultMap通常的标签组成
MyBatis整合Spring
整合思路
- SqlSessionFactory对象应该放到Spring容器中作为单例存在
- 传统Dao的开发方式中,应该从Spring容器中获得SqlSession对象
- Mapper代理形式中,应该从Spring容器中直接获得Mapper的代理对象
- 数据库的连接以及数据库连接池事务管理都交给Spring容器来完成
整合步骤
导入需要的依赖
- Spring的jar包
- MyBatis的jar包
- Spring+MyBatis的整合包。
- MySql的数据库驱动jar包。
- 数据库连接池的jar包
创建配置文件
- 数据库连接及连接池
- 事务管理(暂时可以不配置)
- SqlSessionFactory对象,配置到Spring容器中
- Mapper接口代理对象或者是Dao实现类配置到Spring容器中
Spring与MyBatis整合后Dao的开发
- 传统的Dao开发方式
- 使用Mapper代理的方式
- 直接配置Mapper代理
- 使用扫描包配置Mapper代理
传统Dao开发方式
直接配置Mapper代理方式式开发Dao
package com.zella.mybatis.test; import com.zella.mybatis.mapper.UserMapper; import com.zella.mybatis.pojo.User; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.Date; import java.util.List; public class UserMapperTest { private ApplicationContext context; @Before public void setUp() { this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testQueryUserById() { UserMapper userMapper = this.context.getBean(UserMapper.class); System.out.println(userMapper.queryUserById(1)); } @Test public void testQueryUserByUsername() { // 获取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); List<User> list = userMapper.queryUserByUsername("张"); for (User user : list) { System.out.println(user); } } @Test public void testSaveUser() { // 获取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三国"); userMapper.saveUser(user); System.out.println(user); } }
使用扫描包形式配置Mapper方式开发Dao
MyBatis逆向工程
*拓展内容
各种类型类的定义
PO与VO
DO
PO
BO
VO
DTO
POJO
DAO
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
所有评论(0)