目录
一、什么是MyBatis?
MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架。
MyBatis框架也被称之为ORM (Object/Relation Mapping,即对象关系映射)框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化(保存)到关系型数据库的表中。
之前:SSH---> Spring + Struts + Hibernate
现在:SSM--> Spring + Spring MVC + MyBatis
二、MyBatis的下载和使用
下载地址: https://github.com/mybatis/mybatis-3/releases
使用MyBatis框架非常简单,只需在应用程序中引入MyBatis的核心包和lib目录中的依赖包即可。
注意:如果底层采用的是MySQL数据库,那么还需要将MySQL数据库的驱动JAR包添加到应用程序的类路径中;如果采用其他类型的数据库,则同样需要将对应类型的数据库驱动包添加到应用程序的类路径中。
三、MyBatis的工作原理
- (1)读取 MyBatis 配置文件 mybatis-config.xml。mybatis-config.xml作为MyBatis 的全局配置文件,配置了MyBatis的运行环境等信息,其中主要内容是获取数据库连接。
- (2)加载映射文件Mapper.xml。Mapper.xml文件即SQL映射文件,该文件中配置了操作数据库的SQL语句,需要在mybatis-config.xml中加载才能执行。mybatis-config .xml可以加载多个配置文件,每个配置文件对应数据库中的一张表。
- (3)构建会话工厂。通过 MyBatis 的环境等配置信息构建会话工厂SqlSessionFactoryo
- (4)创建SqlSession对象。由会话工厂创建 SqlSession对象,该对象中包含了执行SQL的所有方法。
- (5) MyBatis底层定义了一个Executor接口来操作数据库,它会根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
- (6)在Executor 接口的执行方法中,包含一个MappedStatement类型的参数,该参数是对映射信息的封装,用于存储要映射的SQL语句的id、参数等。Mapper.xml文件中一个 SQL对应一个MappedStatement对象,SQL的id即是MappedStatement的 id。
- (7)输入参数映射。在执行方法时,MappedStatement对象会对用户执行SQL语句的输入参数进行定义(可以定义为Map、List类型、基本类型和POJO类型),Executor执行器会通过MappedStatement对象在执行SQL前,将输入的Java对象映射到SQL语句中。这里对输入参数的映射过程就类似于JDBC编程中对preparedStatement对象设置参数的过程。
- (8)输出结果映射。在数据库中执行完SQL语句后,MappedStatement对象会对SQL执行输出的结果进行定义(可以定义为Map和List类型、基本类型、POJO类型),Executor执行器会通过MappedStatement对象在执行SQL语句后,将输出结果映射至Java对象中。这种将输出结果映射到Java对象的过程就类似于JDBC编程中对结果的解析处理过程。
四、MyBatis入门程序
1、查询客户
在实际开发中,查询操作通常都会涉及到单条数据的精确查询,以及多条数据的模糊查询。接下来,本小节将讲解下如何使用MyBatis框架根据客户编号查询客户信息,以及根据客户名模糊查询客户信息。
1、根据客户编号查询客户信息
(1)在MySQL 数据库中,创建一个名为 mybatis的数据库,在此数据库中创建一个customer表,同时预先插入几条数据。此操作所执行的SQL语句如下所示。
#创建一个名称为mybatis的数据库CREATE DATABASE mybatis;
#使用mybatis数据库
USE mybatis;
#创建一个名称为t_customer的表CREATE TABLE tcustomer (
id int(32) PRIMARY KEY AUTO_INCREMENT,username varchar (50),
jobs varchar (50),
Ip
phone varchar (16)
);
#插入3条数据
INSERT INTO t customer vALUES
('1', 'joy ', 'doctor ', '13745874578');
工NSERT INTO tcustomer VALUES
('2', 'jack', 'teacher', '13521210112');
INSERT INTO t customer VALUES
( '3', 'tom', 'worker', '15179405961');
(2)在 Eclipse中,创建一个名为chapter06 的 Web项目,将MyBatis 的核心JAR包、lib目录中的依赖JAR包,以及 MySQL 数据库的驱动JAR包一同添加到项目的lib目录下,并发布到类路径中。添加后的lib目录如图所示。
(3)由于MyBatis 默认使用log4j输出日志信息,所以如果要查看控制台的输出SQL语句,那么就需要在 classpath路径下配置其日志文件。在项目的src目录下创建 log4j.properties文件。
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.itheima=DEBUG
# 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
(4)在src目录下,创建一个com.itheima.po包,在该包下创建持久化类Customer,并在类中声明id、username、jobs和phone属性,及其对应的getter/setter方法。
package com.qingcheng.ssm.po;
//命名规则
//TCustomer
//表名t_customer------javabean(TbCustomer)
public class Customer {
//主键id
private Integer 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=" + phone + "]";
}
}
(5)在src目录下,创建一个com.itheima.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.itheima.po.Customer">
select * from t_customer where id = #{id}
</select>
</mapper>
在文件中,第2~3行是 MyBatis 的约束配置,第5~11行是需要程序员编写的映射信息。其中,<mapper>元素是配置文件的根元素,它包含一个 namespace 属性,该属性为这个<mapper>指定了唯一的命名空间,通常会设置成“包名+SQL映射文件名”的形式。子元素<select>中的信息是用于执行查询操作的配置,其 id 属性是<select>元素在映射文件中的唯一标识;parameterType 属性用于指定传入参数的类型,这里表示传递给执行SQL的是一个Integer类型的参数;resultType属性用于指定返回结果的类型,这里表示返回的数据是Customer类型。在定义的查询SQL语句中,“#()”用于表示一个占位符,相当于“?”,而“#[id)”表示该占位符待接收参数的名称为id。
(6)在src目录下,创建MyBatis的核心配置文件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"><!-- 上面是mybatis的核心约束 -->
<configuration>
<environments default="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="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/itheima/mapper/CustomerMapper.xml" />
</mappers>
</configuration>
(7)在src目录下,创建一个com.itheima.test包,在该包下创建测试类MybatisTest,并在类中编写测试方法findCustomerByIdTest()。
/**
*入门程序测试类
*/
@Test
public void findCustomerById() throws IOException {
//1.读取Mybatis的核心配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//2.根据配置文件构建一个SqlsessionFactory
SqlSessionFactory sqlsessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3.根据SqlsessipnFactory创建Sqlsession
SqlSession sqlSession = sqlsessionFactory.openSession();
//4.利用Sqlsession执行Mapper文件中定义的sql语句,并返回结果
Customer customer = sqlSession.selectOne("com.itheima.mapper.CustomerMapper.findCustomerById",2);
//5.打印输出结果
System.out.println(customer);
//6.关闭Sqlsession
sqlSession.close();
}
(8)使用JUnit4测试执行findCustomerByldTest()方法后,控制台的输出结果
2、根据客户名模糊查询客户信息
模糊查询的实现非常简单,只需要在映射文件中通过<select>元素编写相应的SQL 语句,并通过SqlSession的查询方法执行该SQL即可。其具体实现步骤如下。
(1)在映射文件 CustomerMapper.xml中,添加根据客户名模糊查询客户信息列表的SQL语句,具体实现代码如下。
<!--根据客户名模糊查询客户信息列表-->
<select id="findcustomerByName" parameterType="String"
resultType="com.itheima. po. Customer">
select * from t_customer where username like '%${value}% '</select>
与根据客户编号查询相比,上述配置代码中的属性id、parameterType和 SQL语句都发生相应变化。其中,SQL语句中的“${}”用来表示拼接SQL的字符串,即不加解释的原样输出。“${value}”表示要拼接的是简单类型参数。
在使用“${}”进行SQL字符串拼接时,无法防止SQL注入问题。所以想要既能实现模糊查询,又要防止SQL注入,可以对上述映射文件CustomerMapper.xml中模糊查询的select语句进行修改,使用MySQL中的concat()函数进行字符串拼接。具体修改示例如下所示。
select * from t_customer where username like concat ('%',#{value),'%')
( 2)在测试类 MybatisTest中,添加一个测试方法 findCustomerByNameTest(),其代码如下所示。
/**
*根据用户名称来模糊查询用户信息列表*/
@Test
public void findcustomerByNameTest () throws, Exception{
//1.读取配置文件
String resource = "mybatis-config.xml";
InputStream inputstream = Resources.getResourceAsstream(resource);//2.根据配置文件构建 SqlsessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlsessionFactoryBuilder().build(inputStream) ;
//3.通过SqlsessionEactory创建Sqlsession
SqlSession sqlSession= sqlSessionFactory.openSession();// 4. Sqlsession执行映射文件中定义的SQL,并返回映射结果
List<Customer> customers = sqlSession.selectList ("com.itheima,mapper"
+".CustomerMapper.findCustomerByName", "j");
for (Customer customer : customers) {
//打印输出结果集
system. out.println (customer);
}
//5.关闭SqlSessionsqlSession.close();
}
从上述代码可以看出,findCustomerByNameTest()方法只是在第4步时与根据客户编号查询的测试方法有所不同,其他步骤都一致。在第4步时,由于可能查询出的是多条数据,所以调用的是SqlSession 的selectList()方法来查询返回结果的集合对象,并使用for 循环输出结果集对象。
至此,MyBatis 入门程序的查询功能就已经讲解完成。从上面两个查询方法中可以发现,MyBatis 的操作大致可分为以下几个步骤。
- (1)读取配置文件。
- (2)根据配置文件构建SqlSessionFactory。
- (3)通过 SqlSessionFactory创建SqlSession。
- (4)使用SqlSession对象操作数据库(包括查询、添加、修改、删除以及提交事务等)
- (5)关闭SqlSession。
2、添加客户
在MyBatis 的映射文件中,添加操作是通过<insert>元素来实现的。例如,向数据库中的t_customer表中插入—条数据可以通过如下配置来实现。
<!-添加客户信息-->
<insert id="addCustomer" parameterType="com.itheima.po.customer">
insert into t_customer (username, jobs, phone)
values(#{username], #{jobs} , # {phone })
</insert>
在上述配置代码中,传入的参数是一个Customer类型,该类型的参数对象被传递到语句中时,#{username}会查找参数对象Customer 的username属性(#{jobs}和#{phone}也是一样),并将其属性值传入到SQL语句中。为了验证上述配置是否正确,下面编写一个测试方法来执行
/**
*添加客户*/
@Test
public void addCustomerTest () throws, Exception{
//1.读取配置文件
String resource = "mybatis-config.xml";
InputStream inputstream = Resources.getResourceAsstream(resource);//2.根据配置文件构建 SqlsessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlsessionFactoryBuilder().build(inputStream) ;
//3.通过SqlsessionEactory创建Sqlsession
SqlSession sqlSession= sqlSessionFactory.openSession();//4.SqlSession执行添加操作
//4.1创建Customer对象,并向对象中添加数据Customer customer =new Customer();
customer.setUsername("rose");
customer.setJobs ("student");
customer.setPhone("13333533092");
//4.2执行Sqlsession的插入方法,返回的是SQL语句影响的行数int rows = sqlSession.insert("com. itheima.mapper"
+".CustomerMapper.addCustomer", customer);
//4.3通过返回结果判断插入操作是否执行成功
if (rows > 0){
System.out.println("您成功插入了"+rows+”条数据!");}else{
System. out.println("执行插入操作失败!!! ");}
//4.4提交事务
sqlSession.commit();//没有提交事务,可运行成功,但数据库没有更改//5.关闭SqlSession
sqlSession.close();
}
在上述代码的第4步操作中,首先创建了Customer对象,并向Customer对象中添加了属性值;然后通过SqlSession对象的 insert()方法执行插入操作,并通过该操作返回的数据来判断插入操作是否执行成功;最后通过SqlSesseion的commit()方法提交了事务,并通过 close()方法关闭SqlSession。
3、更新用户
MyBatis 的更新操作在映射文件中是通过配置<update>元素来实现的。如果需要更新用户数据,可以通过如下代码配置来实现。
<!--更新客户信息-->
<update id="updateCustomer" parameterType="com.itheima.po.Customer">
update t_customer set
username=#(username], jobs=#[jobs } , phone=# ( phone}where id=#{id)
</update>
在测试类MybatisTest中,添加测试方法updateCustomerTest(),将id为4的用户职业修改为programmer,电话修改为13311111111。
/**
*更新客户*/
@Test
public void updateCustomerTest () throws, Exception{
//1.读取配置文件
String resource = "mybatis-config.xml";
InputStream inputstream = Resources.getResourceAsstream(resource);//2.根据配置文件构建 SqlsessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlsessionFactoryBuilder().build(inputStream) ;
//3.通过SqlsessionEactory创建Sqlsession
SqlSession sqlSession= sqlSessionFactory.openSession();//4.SqlSession执行更新操作
//4.1创建Customer对象,并对对象中的数据进行模拟更新Customer customer =new Customer();
customer.setId(4);
customer.setUsername("rose");
customer.setJobs ("programmer");
customer.setPhone("13311111111");
//4.2执行Sqlsession的更新方法,返回的是SQL语句影响的行数int rows = sqlSession.update("com. itheima.mapper"
+".CustomerMapper.updateCustomer", customer);
//4.3通过返回结果判断更新操作是否执行成功
if (rows > 0){
System.out.println("您成功修改了"+rows+”条数据!");}else{
System. out.println("执行修改操作失败!!! ");}
//4.4提交事务
sqlSession.commit();//没有提交事务,可运行成功,但数据库没有更改//5.关闭SqlSession
sqlSession.close();
}
4、删除客户
MyBatis的删除操作在映射文件中是通过配置<delete>元素来实现的。在映射文件CustomerMapper.xml中添加删除客户信息的SQL语句,其示例代码如下。
<!--删除客户信息-->
<delete id="deleteCustomer" parameterType="Integer">
delete from t_customer where id=#(id}
</ delete>
从上述配置的SQL语句中可以看出,我们只需要传递一个id值就可以将数据表中相应的数据删除。
要测试删除操作的配置十分简单,只需使用SqlSession对象的delete()方法传入需要删除数据的 id值即可。在测试类MybatisTest中,添加测试方法 deleteCustomerTest(),该方法用于将id 为4的客户信息删除,其代码如下所示。
/**
*删除客户*/
@Test
public void deleteCustomerByIdTest () throws, Exception{
//1.读取配置文件
String resource = "mybatis-config.xml";
InputStream inputstream = Resources.getResourceAsstream(resource);//2.根据配置文件构建 SqlsessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlsessionFactoryBuilder().build(inputStream) ;
//3.通过SqlsessionEactory创建Sqlsession
SqlSession sqlSession= sqlSessionFactory.openSession();//4.SqlSession执行删除操作
// 4.1执行SqlSession的删除方法,返回的是SQL语句影响的行数int rows = sqlSession. delete ( "com.itheima .mapper"
+".customerMapper.deleteCustomer", 4);
//4.2通过返回结果判断删除操作是否执行成功
if (rows > 0){
System.out.println("您成功删除了"+rows+”条数据!");}else{
System. out.println("执行删除操作失败!!! ");}
//4.3提交事务
sqlSession.commit();//没有提交事务,可运行成功,但数据库没有更改//5.关闭SqlSession
sqlSession.close();
}
至此,MyBatis 入门程序的增删改查操作已经讲解完成。