MyBatis作用
- MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
- MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- MyBatis可以使用简单的XML用于配置和原始映射,将接口和Java的POJO类映射成数据库中的记录
使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
历史
-
原是apache的一个开源项目iBatis
2010年6月这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。
为什么要使用MyBatis?
JDBC
SQL夹在Java代码块里,耦合度高导致硬编码内伤
维护不易且实际开发需求中sql是有变化,频繁修改的情况多见
要自已创建connection、创建statement、手动设置参数、结果集检索等
Hibernate
长难复杂SQL,对于Hibernate而言处理也不容易
内部自动生产的SQL,不容易做特殊优化。
基于全映射的全自动框架,javaBean存在大量字段时无法只映射部分字段。导致数据库性能下降。
Mybatis
对开发人员而言,核心sql还是需要自己优化
MyBatis是一个半自动化的持久化层框架。
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。
MyBatis入门程序
1. 下载Mybatis核心包
http://www.mybatis.org/mybatis-3/getting-started.html
https://github.com/mybatis/mybatis-3/releases
2.创建工程,引入MyBatis核心包及依赖包3.创建customer表,建立与表对象的domain
4.创建MyBatis核心配置文件SqlMappingConfig.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> <!-- spring整合后 environments配置将废除 使用spring中的连接池 --> <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="1234" /> </dataSource> </environment> </environments> </configuration>
5.创建与表对象的关系映射Mapping文件编写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"> <mapper namespace="myTest"> <!--根据cust_id查询客户--> <select id="queryCustomerById" parameterType="Int" resultType="com.itlike.domain.Customer"> SELECT * FROM `customer` WHERE cust_id = #{cust_id} </select> </mapper>
6.在核心配置文件当中引入Mapping
<!--加载映射文件--> <mappers> <mapper resource="com/myxq/domain/Customer.xml"></mapper> </mappers>
7.创建工厂,执行sql语句
MyBatis核心Api
SqlSessionFactoryBuilder:用于创建SqlSessionFacoty
SqlSessionFacoty:一旦创建完成就不需要SqlSessionFactoryBuilder了
因为SqlSession是通过SqlSessionFactory创建的
所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。
SqlSessionFactory:创建sqlSession的工厂,是一个接口
接口中定义了openSession的不同重载方法
SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。
SqlSession:连接到数据库的一个会话
sqlSession中定义了数据库操作方法。
每个线程都应该有它自己的SqlSession实例
SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围
绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。
MyBatis架构
MyBatis-查询
- 封装工具类
public class MyBatisUtils {
public static final SqlSessionFactory sessionFactory;
//静态代码块 只加载一次
static {
//1 加载配置文件的
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//2 读取配置文件 在src目录下
InputStream resourceAsStream = null;
try {
resourceAsStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
//3 获取session工厂 session就是与数据库的一个会话
sessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
}
public static SqlSession openSession(){
return sessionFactory.openSession();
}
}
查询所有
配置sql语句在控制台打印
在SqlMappingConfig.xml
模糊查询
查询失败示例:
为什么:对于参数#{cust_name}来说,该查询语句执行时,会转化为sql语句
SELECT * FROM customer WHERE cust_name LIKE '%?'%'
,也就是#{cust_name}=‘cust_name’ 多了一对单引号 因此产生语法错误
解决方法:
先介绍#{}与${}的区别
#{}
表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值
自动进行java类型和jdbc类型转换
#{}可以有效防止sql注入
#{}可以接收简单类型值或pojo属性值
如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称
${}
表示拼接sql串
通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换
${}可以接收简单类型值或pojo属性值
如果parameterType传输单个简单类型值,${}括号中只能是value ${value}
注意采用${}方式无法防止sql注入,所以还是使用#{},只不过是#{一个名称} 而传参数为"%李%" 就是把%李%当做一个占位符
MyBatis-插入一条数据
一定要手动添加事务,若无提交事务则添加不了到数据库
获取最后插入的id
背景:引导用户注册时需让用户填写的信息越少越好,注册完之后再调至完善个人信息的窗口,所以需要获取最后插入的那1条记录,在配置插入语句的前面加上以下内容,最后在提交事务语句后就可以获取id了
更新操作
先找出要更新的对象,将要修改的字段设置好,传入update方法,删除操作也类似
Customer customer = sqlSession.selectOne("queryCustomerById", 12);
customer.setCust_name("孙悟空");
sqlSession.update("updateCustomer", customer);
删除操作
Customer customer = sqlSession.selectOne("queryCustomerById", 13);
sqlSession.delete("deleteCustomer", customer);