Mybatis是当前主流的Java持久层框架之一,是一种ORM框架。性能优异,有高度的灵活性、可优化性、易于维护。Mybatis是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或者注解进行配置和原始映射,用以将接口和Java的POJO映射成数据库中的记录。Mybatis也被称为ORM(对象关系映射)框架,通过Java对象与数据表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。
一、Mybatis的工作原理
图片来源:传智播客
具体步骤如下:
- 读取配置文件mybatis-config.xml。其作为Mybatis的全局配置文件,配置了Mybatis的运行环境等信息,主要内容是获取数据库连接。
- 加载映射文件Mapper.xml。该文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,,需要在mybatis-config.xml中加载才能执行。mybatis-config.xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
- 构建会话工厂。通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory。
- 创建SqlSession对象。由会话工厂创建SqlSession对象,该对象中包含了执行SQL的所有方法。
- MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
- 在Executor接口的执行方法中,包含了一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml文件的一个SQL对应一个MappedStatement对象,SQL的id即使MappedStatement的id。
- 输入映射参数。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List、基本类型和POJO类型),Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。
- 输出结构集。执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义。
二、入门程序
1、查询客户
创建数据库后,创建项目,同时引入MyBatis的核心jar包,同时使用log4j输出日志信息。创建po包,在该包下创建持久化类Customer:
/**
* 客户持久化类
* @author Youguangfu
*
*/
public class Customer {
private Integer id ;//用户id
private String username;//客户名称
private String jobs;//职业
private String phone;//电话
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getJobs() {
return jobs;
}
public void setJobs(String jobs) {
this.jobs = jobs;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return "Customer [id = "+id+",username = "+username+",jobs = "+jobs+",phone]";
}
}
创建mapper包,并在包中创建映射文件CustomerMapper.xml如下:
<?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.itheima.mapper.CustomerMapper">
<!-- 根据客户编号获取客户信息 -->
<select id="findCustomerById" parameterType = "Integer" resultType = "com.po.Customer">
select * from t_customer where id = #{id}
</select>
</mapper>
<mapper>元素时配置文件的根元素,包含一个namespace属性,该属性为这个<mapper>指定了唯一的命名空间,通常会设置为“包名+SQL映射文件名”的形式。子元素<select>中的信息是用于执行查询操作的配置,其id属性是<select>元素在映射文件中唯一标识;parameterType属性用于指定传入参数的类型,这里表示传递给执行SQL的是一个Integer类型的参数;rasultType属性用于指定返回结果的类型。“#{}”是一个占位符。核心配置文件mybatis-config.xml如下:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置环境 默认的环境id为mysql -->
<environments default="mysql">
<!-- 配置id为mysql的数据库环境 -->
<environment id="mysql">
<!-- 使用JDBC事务管理 -->
<transactionManager type="JDBC"/>
<!-- 数据连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="0213"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 配置mapper的位置 -->
<mapper resource="com/mapper/CustomerMapper.xml"/>
<mapper resource="com/mapper/UserMapper.xml"/>
</mappers>
</configuration>
测试文件:
* 根据客户id查询客户信息
* @throws Exception
*/
@Test
public void findCustomerById() throws Exception {
//读取配置文件
String reource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(reource);
//根据配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过selSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession执行映射文件中定义的Sql,并返回映射结果
Customer customer = sqlSession.selectOne("com.itheima.mapper.CustomerMapper.findCustomerById",1);
}
System.out.println(customer);
//关闭SQLSession
sqlSession.close();
}
该文件中,先通过输入流读取配置文件,然后根据配置文件构建了SqlSessionFactory对象。接下来通过SqlSessionFactory对象创建SqlSession对象,并通过SqlSession对象的selectOne方法执行查询操作。
模糊查询的实现如下,只需要在映射文件中通过<select>元素编写相应的SQL语句并通过SqlSession的查询方法执行该SQL即可。
<!-- 根据客户名模糊查询客户信息列表 -->
<select id="findCustomerByName" parameterType = "String" resultType = "com.itheima.po.Customer">
select * from t_customer where username like '%${value}'
</select>
***:在使用“${}”进行字符串拼接时,无法防止SQL注入问题,可以使用函数conncat()进行字符串进行拼接
测试方法:
@Test
public void findCustomerById() throws Exception {
//读取配置文件
String reource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(reource);
//根据配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过selSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession执行映射文件中定义的Sql,并返回映射结果
//Customer customer = sqlSession.selectOne("com.itheima.mapper.CustomerMapper.findCustomerById",1);
List<Customer> customers = sqlSession.selectList("com.itheima.mapper.CustomerMapper.findCustomerByName",'t');
for (Customer customer : customers) {
System.out.println(customer);
}
System.out.println(customer);
//关闭SQLSession
sqlSession.close();
MyBatis的操作大致分为以下几个步骤:
- 读取配置文件
- 根据配置文件构建SqlSessionFactory
- 通过SqlSessionFactory创建SqlSession
- shiyongSqlSession对象操作数据库
- 关闭SqlSession
2、添加用户
添加操作使用<insert>元素来实现的。例如:
<!-- 添加客户信息 -->
<insert id="addCustomer" parameterType = "com.po.Customer" >
insert into t_customer(username,jobs,phone) values(#{username},#{jobs},#{phone})
</insert>
上述代码中,传入的参数是一个Customer类型,该类型的参数对象被传递到语句中时,#{username}会查找参数对象Customer的username属性,并将其属性值传入到SQL语句中,测试方法:
* 添加用户
* @throws Exception
*/
@Test
public void addCustomerTest() throws Exception {
//读取配置文件
String reource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(reource);
//根据配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过selSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession执行映射文件中定义的Sql,并返回映射结果
//创建Customer对象 并添加数据
Customer customer = new Customer();
customer.setUsername("gg");
customer.setJobs("web");
customer.setPhone("22222222");
//执行SQLSession的插入方法,返回的是影响行数
int rows = sqlSession.insert("com.mapper.CustomerMapper.addCustomer",customer);
//通过返回结果判断插入操作是否成功
if(rows > 0) {
System.out.println("ok");
}else {
System.out.println("no");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
首先创建Customer对象,并想Customer对象中添加了属性值,然后通过SqlSession对象的insert方法执行插入操作,并判断是否执行成功。
3、更新客户
通过配置<update>元素实现更新操作:
<!-- 更新客户信息 -->
<update id="updateCustomer" parameterType="com.po.Customer">
update t_customer set username = #{username},jobs = #{jobs},phone = #{phone}
where id = #{id}
</update>
/**
* 更新客户
* @throws Exception
*/
@Test
public void updateCustomerTest() throws Exception {
String reource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(reource);
//根据配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过selSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession执行映射文件中定义的Sql,并返回映射结果
//创建Customer对象 并添加数据
Customer customer = new Customer();
customer.setId(3);
customer.setUsername("rose");
customer.setJobs("python");
customer.setPhone("333333333333333333");
//执行SQLSession的更新方法 返回是语句影响行数
int rows = sqlSession.update("com.mapper.CustomerMapper.updateCustomer",customer);
if(rows >0) {
System.out.println("ok");
}else {
System.out.println("no");
}
sqlSession.commit();
sqlSession.close();
}
4、删除客户
删除操作通过<delete>元素实现:
<!-- 删除用户 -->
<delete id="deleteCustomer" parameterType="Integer">
delete from t_customer where id = #{id}
</delete>
/**
* 删除用户
* @throws Exception
*/
@Test
public void deleteCustomerTest() throws Exception {
String reource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(reource);
//根据配置文件构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//通过selSessionFactory创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession执行映射文件中定义的Sql,并返回映射结果
int rows = sqlSession.delete("com.mapper.CustomerMapper.deleteCustomer",3);
if(rows >0) {
System.out.println("ok");
}else {
System.out.println("no");
}
sqlSession.commit();
sqlSession.close();
}