目录
6.1 MyBatis概述
MyBatis是一个支持普通SQL查询,存储过程以及高级映射的持久框架,消除了所有JDBC代码和参数的手动设置以及对结果集的检索,使用简单的XML或者注解进行配置和原始映射,用以将接口和java的对象映射成数据库中的记录,简而言之,让程序员使用面向对象的思想操作数据库。
6.1.1 什么是MyBatis?
MyBatis框架又叫做ORM框架。
ORM,是一种为解决面向对象与关系型数据库中数据类型不匹配的技术,通过描述java对象与数据库表之间的映射关系自动将java应用程序中的对象持久化到关系数据库的表中。
使用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象(Persisent Object,PO),而ORM框架则会通过映射关系将这些面向对象的操作转换成底层的SQL操作。
常见的ORM框架:
1. Hibernate
一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过Hibernate提供的方法完成持久层操作。开发者并不需要熟练地掌握SQL语句的编写,Hibernate会根据制定的存储逻辑自动生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。然而Hibernate自身存在着一些缺点,例如它在多表关联时,对SQL查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化SQL来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
2. MyBatis
一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,MyBatis需要手动匹配提供POJO、SQL和映射关系,而Hibernate只需提供POJO和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写SQL要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。
6.1.2 MyBatis的下载和使用
通过官网可以下载,下载解压后可以得到一个mybatis+版本号的文件,里面有核心包和lib包,包含了开发需要的jar压缩包
使用MyBatis框架非常简单,只需在应用程序中引入MyBatis的核心包mybatis-3.4.2.jar和lib目录中的依赖包即可,同时还应该添加底层数据库的驱动jar包到lib文件夹下,同时发布到类路径。
- 不同的底层数据库的数据库驱动jar包是不一样的
实例一 MyBatis入门级别的程序
1. 查询用户
根据用户id查询用户信息(主要是通过查询用户表中的主键,这是用户唯一的标识)
步骤1.1
在Mysql数据库中创建一个db_mybatis的数据库,并创建一个表t_user表,同时预先添加几条数据,对应的如下
步骤1.2
.创建项目,并引入jar包
步骤1.3
MyBatis默认使用log4j输出日志信息,所以如果要查看控制台的输出SQL语句,需要在classpath路径下配置日志文件,在src的目录下创建文件log4j.properties,内容如下
# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.com.ssm=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
包含全局的日志配置、MyBatis的日志配置和控制台输出,其中MyBatis的日志配置用于将com.ssm包下所有类的日志记录级别设置为DEBUG。
步骤1.4
创建持久化类User,声明属性和对应的方法
package com.ssm.po;
public class User {
Integer id;
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;
}
String username;
String jobs;
String phone;
public String toString()
{
return "User[id="+id+",username="+username+",jobs="+jobs+",phone="+phone+"]";
}
}
持久化类User与普通的JavaBean并没有什么区别,只是其属性字段与数据库中的表字段相对应。实际上,User就是一个POJO(普通Java对象)。MyBatis就是采用POJO作为持久化类来完成对数据库操作的。
步骤1.5
创建映射文件UserMapper.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.ssm.mapper.UserMapper">
<!--根据用户编号获取用户信息 -->
<select id="findUserById" parameterType="Integer" resultType="com.ssm.po.User">
select * from t_user where id=#{id}
</select>
</mapper>
< mapper>元素是配置文件的根元素,包含一个namespace属性,该属性为< mapper>元素指定了唯一的命名空间,通常会设置成“包名+SQL映射文件名”的形式。子元素< select>中的信息是用于执行查询操作的配置,其id属性是< select>元素在映射文件中的唯一标识;parameterType属性用于指定传入参数的类型,这里表示传递给执行SQL的是一个Integer类型的参数;resultType属性用于指定返回结果的类型,这里表示返回的数据是Customer类型。在定义的查询SQL语句中,“#{}”用于表示一个占位符,相当于“?”;而“#{id}”表示该占位符待接收参数的名称为id。
步骤1.6
创建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">
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db_mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/ssm/mapper/UserMapper.xml" />
</mappers>
</configuration>
< configuration>元素中的内容是开发人员需要编写的配置信息。这里按照< configuration>子元素的功能将配置分为了两个步骤:第1步,配置环境;第2步,配置mapper的位置。
步骤1.7
创建测试类,编写测试方法
package com.ssm.test;
import java.io.InputStream;
import java.util.List;
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 com.ssm.po.User;
public class MybatisTest {
@Test
public void findUserByIdTest() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("com.ssm.mapper.UserMapper.findUserById", 1);
System.out.println(user.toString());
sqlSession.close();
}
}
首先通过输入流读取了配置文件,然后根据配置文件构建了SqlSessionFactory对象。接下来通过SqlSessionFactory对象又创建了SqlSession对象,并通过SqlSession对象的selectOne()方法执行查询操作。selectOne()方法的第1个参数表示映射SQL的标识字符串,由UserMapper.xml中< mapper>元素的namespace属性值+< select>元素的id属性值组成;第2个参数表示查询所需要的参数,这里查询的是用户表中id为1的用户。为了查看查询结果,这里使用了输出语句输出查询结果信息。最后,程序执行完毕时,关闭了SqlSession。
使用JUnit4测试执行findUserByIdTest()方法后,结果如下
2. 根据用户模糊查询用户信息
步骤2.1
在映射文件UserMapper中添加根据用户名模糊查询用户信息的列表的SQL语句
<!--根据用户名模糊查询用户信息 -->
<select id="findUserByName" parameterType="String" resultType="com.ssm.po.User">
select * from t_user where username like '%${value}%'
</select>
SQL语句中的 “ $ { }”用来表示拼接SQL的字符串,即不加解释地原样输出。“$ {value}”表示要拼接的是简单类型参数。
注意
在使用“$ {}”进行SQL字符串拼接时,无法防止SQL注入问题。想要既能实现模糊查询,又能防止SQL注入,可以对上述映射文件UserMapper.xml中模糊查询的select语句进行修改,使用MySQL中的concat函数进行字符串拼接。具体修改示例如下所示。
select * from t_user where username like concat(’%’, ${value},’%’)
步骤2.2
在测试类中添加一个测试方法
@Test
public void findUserByNameTest() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> users = sqlSession.selectList("com.ssm.mapper.UserMapper.findUserByName", "g");
for (User user : users) {
System.out.println(user.toString());
}
sqlSession.close();
}
由于可能查询出多条数据,因此调用SqlSession的selectList()方法来查询返回结果的集合对象,并使用for循环输出结果集对象。
MyBatis框架的大致操作
- 读取配置文件
- 根据配置文件构建SqlSessionFactory
- 通过SqlSessionFactory创建SqlSession
- 使用SqlSession对象操作数据库
- 最后要记得关闭SqlSession
6.2.2 添加客户
第一步
在MyBatis的映射文件中,添加操作的SQL语句,添加配置
<!--添加客户信息 -->
<insert id="addUser" parameterType="com.ssm.po.User">
insert into t_user(username,jobs,phone) values(#{username},#{jobs},#{phone})
</insert>
传入的参数是一个User类型,该类型的参数对象被传递到语句中时,#{username}会查找参数对象User的username属性,#{jobs}和#{phone}也是一样的,并将其属性值传入SQL语句中。
第二步
为了验证正确性,在测试类中添加一个方法
@Test
public void addUserTest() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setUsername("tom");
user.setJobs("worker");
user.setPhone("13624589654");
int rows = sqlSession.insert("com.ssm.mapper.UserMapper.addUser", user);
if (rows > 0) {
System.out.println("成功添加" + rows + "条数据!");
} else {
System.out.println("添加数据失败!");
}
sqlSession.commit();
sqlSession.close();
}
6.2.3 更新用户(步骤同上)
第一步
在MyBatis的映射文件中,添加操作的SQL语句,添加配置
<!--更新用户信息 -->
<update id="updateUser" parameterType="com.ssm.po.User">
update t_user set username=#{username},jobs=#{jobs},phone=#{phone} where id=#{id}
</update>
第二步
为了验证正确性,在测试类中添加一个方法
@Test
public void updateUserTest() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = new User();
user.setId(4);
user.setUsername("tom");
user.setJobs("teacher");
user.setPhone("13624589654");
int rows = sqlSession.update("com.ssm.mapper.UserMapper.addUser", user);
if (rows > 0) {
System.out.println("成功修改了" + rows + "条数据!");
} else {
System.out.println("修改数据失败!");
}
sqlSession.commit();
sqlSession.close();
}
6.2.4 删除用户(步骤同上)
第一步
MyBatis的删除操作在映射文件中是通过配置< delete>元素来实现的。在映射文件UserMapper.xml中添加删除客户信息的SQL语句,
<delete id="deleteUser" parameterType="Integer">
delete from t_user where id=#{id}
</delete>
第二步,添加测试方法
@Test
public void deleteUserTest() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
int rows = sqlSession.delete("com.ssm.mapper.UserMapper.deleteUser", 4);
if (rows > 0) {
System.out.println("成功删除了" + rows + "条数据!");
} else {
System.out.println("删除数据失败!");
}
sqlSession.commit();
sqlSession.close();
}