查询客户
在实际开发中,查询操作通常都会涉及到单条数据的精确查询,以及多条数据的模糊查询。那么使用MyBatis框架是如何进行这两种查询的呢?接下来,本小节将讲解下如何使用MyBatis框架根据客户编号查询客户信息,以及根据客户名模糊查询客户信息。
1.根据客户编号查询客户信息
根据客户编号查询客户信息主要是通过查询客户表中的主键(这里表示唯一的客户编号)来实现的,其具体实现步骤如下:
(1)在MySQL数据库中,创建一个名为mybatis的数据库,在此数据库中创建一个t_customer表,同时预先插入几条数据。此操作所执行的SQL语句如下所示。
# 创建一个名称为mybatis的数据库
CREATE DATABASE mybatis;
# 使用mybatis数据库
USE mybatis;
# 创建一个名称为t_customer的表
CREATE TABLE t_customer (
id int(32) PRIMARY KEY AUTO_INCREMENT,
username varchar(50),
jobs varchar(50),
phone varchar(16)
);
# 插入3条数据
INSERT INTO t_customer VALUES ('1', 'joy', 'doctor', '13745874578');
INSERT INTO t_customer VALUES ('2', 'jack', 'teacher', '13521210112');
INSERT INTO t_customer VALUES ('3', 'tom', 'worker', '15179405961');
完成上述操作后,数据库t_customer表中的数据如图1所示。
图1 t_customer表
(2)在Eclipse中,创建一个名为chapter06的Web项目,将MyBatis的核心JAR包、lib目录中的依赖JAR包,以及MySQL数据库的驱动JAR包一同添加到项目的lib目录下, 并发布到类路径中。添加后的lib目录如图2所示。
图2 MyBatis相关JAR包
(3)由于MyBatis默认使用log4j输出日志信息,所以如果要查看控制台的输出SQL语句,那么就需要在classpath路径下配置其日志文件。在项目的src目录下创建log4j.properties文件,编辑后的内容如文件1所示。
文件1 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
在文件1中,包含了全局的日志配置、MyBatis的日志配置和控制台输出,其中MyBatis的日志配置用于将com.itheima包下所有类的日志记录级别设置为DEBUG。
由于log4j文件中的具体内容已经超出了本书范围,所以这里不过多讲解,读者可自行查找资料学习。上述配置文件代码也不需要读者全部手写,在MyBatis使用手册中的Logging小节,可以找到如图3所示的配置信息,只需将其复制到项目的log4j配置文件中,并对MyBatis的日志配置信息进行简单修改即可使用。
图3 MyBatis使用手册中的Logging配置
(4)在src目录下,创建一个com.itheima.po包,在该包下创建持久化类Customer,并在类中声明id、username、jobs和phone属性,及其对应的getter/setter方法,如文件2所示。
文件2 Customer.java
1 package com.itheima.po;
2 /**
3 * 客户持久化类
4 */
5 public class Customer {
6 private Integer id; // 主键id
7 private String username; // 客户名称
8 private String jobs; // 职业
9 private String phone; // 电话
10 public Integer getId() {
11 return id;
12 }
13 public void setId(Integer id) {
14 this.id = id;
15 }
16 public String getUsername() {
17 return username;
18 }
19 public void setUsername(String username) {
20 this.username = username;
21 }
22 public String getJobs() {
23 return jobs;
24 }
25 public void setJobs(String jobs) {
26 this.jobs = jobs;
27 }
28 public String getPhone() {
29 return phone;
30 }
31 public void setPhone(String phone) {
32 this.phone = phone;
33 }
34 @Override
35 public String toString() {
36 return "Customer [id=" + id + ", username=" + username +
37 ", jobs=" + jobs + ", phone=" + phone + "]";
38 }
39 }
从上述代码可以看出,持久化类Customer与普通的JavaBean并没有什么区别,只是其属性字段与数据库中的表字段相对应。实际上,Customer就是一个POJO(普通Java对象),MyBatis就是采用POJO作为持久化类来完成对数据库操作的。
(5)在src目录下,创建一个com.itheima.mapper包,并在包中创建映射文件CustomerMapper.xml,编辑后如文件3所示。
文件3 CustomerMapper.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4 <!-- namespace表示命名空间 -->
5 <mapper namespace="com.itheima.mapper.CustomerMapper">
6 <!--根据客户编号获取客户信息 -->
7 <select id="findCustomerById" parameterType="Integer"
8 resultType="com.itheima.po.Customer">
9 select * from t_customer where id = #{id}
10 </select>
11 </mapper>
在文件3中,第2~3行是MyBatis的约束配置,第5~11行是需要程序员编写的映射信息。其中,<mapper>元素是配置文件的根元素,它包含一个namespace属性,该属性为这个<mapper>指定了唯一的命名空间,通常会设置成“包名+SQL映射文件名”的形式。子元素<select>中的信息是用于执行查询操作的配置,其id属性是<select>元素在映射文件中的唯一标识;parameterType属性用于指定传入参数的类型,这里表示传递给执行SQL的是一个Integer类型的参数;resultType属性用于指定返回结果的类型,这里表示返回的数据是Customer类型。在定义的查询SQL语句中,“#{}”用来表示一个占位符,相当于“?”,而“#{id}”表示该占位符待接收参数的名称为id。
多学一招: 快速获取配置文件的约束信息
在MyBatis的映射文件中,包含了一些约束信息,初学者如果自己动手去编写,不但浪费时间,还容易出错。其实,在MyBatis使用手册中,就可以找到这些约束信息,具体的获取方法如下:
打开MyBatis的使用手册mybatis-3.4.2.pdf,在第2小节Getting started(入门指南)下的2.1.5小节Exploring Mapped SQL Statements中,即可找到映射文件的约束信息。如图4所示。
图4 映射文件的约束信息
在图4中,方框处标注的文件信息就是MyBatis映射文件的约束信息。初学者只需将信息复制到项目创建的XML文件中即可。
(6)在src目录下,创建MyBatis的核心配置文件mybatis-config.xml,编辑后如文件4所示。
文件4 mybatis-config.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
3 "http://mybatis.org/dtd/mybatis-3-config.dtd">
4 <configuration>
5 <!--1.配置环境 ,默认的环境id为mysql-->
6 <environments default="mysql">
7 <!--1.2.配置id为mysql的数据库环境 -->
8 <environment id="mysql">
9 <!-- 使用JDBC的事务管理 -->
10 <transactionManager type="JDBC" />
11 <!--数据库连接池 -->
12 <dataSource type="POOLED">
13 <property name="driver" value="com.mysql.jdbc.Driver" />
14 <property name="url"
15 value="jdbc:mysql://localhost:3306/mybatis" />
16 <property name="username" value="root" />
17 <property name="password" value="root" />
18 </dataSource>
19 </environment>
20 </environments>
21 <!--2.配置Mapper的位置 -->
22 <mappers>
23 <mapper resource="com/itheima/mapper/CustomerMapper.xml" />
24 </mappers>
25 </configuration>
在文件4中,第2~3行是MyBatis的配置文件的约束信息,下面<configuration>元素中的内容就是开发人员需要编写的配置信息。这里按照<configuration>子元素的功能不同,将配置分为了两个步骤:第1步配置了环境,第2步配置了Mapper的位置。关于上述代码中各个元素的详细配置信息将在下一章进行详细讲解,此案例中读者只需要按照上述代码配置即可。
小提示:
上述配置文件同样不需要读者完全手动编写。在MyBatis使用手册mybatis-3.4.2.pdf的2.1.2小节中,已经给出了配置模板(包含约束信息),读者只需要复制过来,依照自己的项目需求修改即可。
(7)在src目录下,创建一个com.itheima.test包,在该包下创建测试类MybatisTest,并在类中编写测试方法findCustomerByIdTest(),如文件5所示。
文件5 MybatisTest.java
1 package com.itheima.test;
2 import java.io.InputStream;
3 import org.apache.ibatis.io.Resources;
4 import org.apache.ibatis.session.SqlSession;
5 import org.apache.ibatis.session.SqlSessionFactory;
6 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
7 import org.junit.Test;
8 import com.itheima.po.Customer;
9 /**
10 * 入门程序测试类
11 */
12 public class MybatisTest {
13 /**
14 * 根据客户编号查询客户信息
15 */
16 @Test
17 public void findCustomerByIdTest() throws Exception {
18 // 1、读取配置文件
19 String resource = "mybatis-config.xml";
20 InputStream inputStream =
21 Resources.getResourceAsStream(resource);
22 // 2、根据配置文件构建SqlSessionFactory
23 SqlSessionFactory sqlSessionFactory =
24 new SqlSessionFactoryBuilder().build(inputStream);
25 // 3、通过SqlSessionFactory创建SqlSession
26 SqlSession sqlSession = sqlSessionFactory.openSession();
27 // 4、SqlSession执行映射文件中定义的SQL,并返回映射结果
28 Customer customer = sqlSession.selectOne("com.itheima.mapper"
29 + ".CustomerMapper.findCustomerById", 1);
30 // 打印输出结果
31 System.out.println(customer.toString());
32 // 5、关闭SqlSession
33 sqlSession.close();
34 }
35 }
在文件5的findCustomerByIdTest()方法中,首先通过输入流读取了配置文件,然后根据配置文件构建了SqlSessionFactory对象。接下来通过SqlSessionFactory对象又创建了SqlSession对象,并通过SqlSession对象的selectOne()方法执行查询操作。selectOne()方法的第1个参数表示映射SQL的标识字符串,它由CustomerMapper.xml中<mapper>元素的namespace属性值+<select>元素的id属性值组成;第2个参数表示查询所需的参数,这里查询的是客户表中id为1的客户。为了查看查询结果,这里使用了输出语句输出查询结果信息。最后,程序执行完毕时,关闭了SqlSession。
使用JUnit4测试执行findCustomerByIdTest()方法后,控制台的输出结果如图5所示。
图5 运行结果
从图5可以看出,使用MyBatis框架已经成功查询出了id为1的客户信息。
2.根据客户名模糊查询客户信息
了解了如何使用MyBatis根据客户编号查询客户信息后,接下来讲解下如何根据客户的名称来模糊查询相关的客户信息。
模糊查询的实现非常简单,只需在映射文件中通过<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注入问题。所以想要既能实现模糊查询,又要防止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、通过SqlSessionFactory创建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、关闭SqlSession
sqlSession.close();
}
从上述代码可以看出,findCustomerByNameTest()方法只是在第4步时与根据客户编号查询的测试方法有所不同,其他步骤都一致。在第4步时,由于可能查询出的是多条数据,所以调用的是SqlSession的selectList()方法来查询返回结果的集合对象,并使用for循环输出结果集对象。
使用JUnit4执行findCustomerByNameTest()方法后,控制台的输出结果如图6所示。
图6 运行结果
从图6可以看出,使用MyBatis框架已成功查询出了客户表中客户名称中带有“j”的2条客户信息。
至此,MyBatis入门程序的查询功能就已经讲解完成。从上面两个查询方法中可以发现,MyBatis的操作大致可分为以下几个步骤:
1) 读取配置文件。
2) 根据配置文件构建SqlSessionFactory。
3) 通过SqlSessionFactory创建SqlSession。
4) 使用SqlSession对象操作数据库(包括查询、添加、修改、删除,以及提交事务等)。
5) 关闭SqlSession。