高级Web技术复习

@Author:HYN

2022年春季,2019级数据科学与大数据技术高级Web技术期中考试复习提纲。

  • Spring的两大特性及其含义
  • Spring的自动装配机制
  • Spring核心容器层组成
  • Spring Bean的作用域
  • Spring MVC框架组合注解
  • SpringMVC页面跳转类型
  • SpringMVC三大组件
  • Mybatis映射文件
  • Mybatis的核心对象
  • 动态SQL元素
  • Mybatis常用注解
  • Mybatis映射文件中常用元素

考题预测

论述题

传统JDBC的劣势是什么?

  • 频繁的创建、释放数据库连接会造成系统资源浪费
  • 代码中的SQL语句硬编码,会造成代码不易于维护
  • JDBC对结果集解析存在硬编码,使得系统不易于维护

Mybatis是什么?

Mybatis是一个支持普通SQL查询、存储及高级映射的持久层框架

什么是ORM?

Mybatis框架是一个ORM框架。所谓的ORM就是一种为了解决面向对象与关系型数据库中数据不匹配的技术。它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的数据表中。

名词解释

  • IOC:控制反转,典型的工厂模式。在使用Spring框架后,对象实例不再有调用者创建,而是由Spring的IOC容器来创建,IoC容器会负责控制程序之间的关系。
  • AOP:面向切面编程,典型的代理模式的体现。AOP是通过预编译方式和运行期间动态代理实现程序功能,也就是说可以在不修改源代码的情况下,给程序统一添加功能。
  • Beans模块:它提供了BeanFactory类,是工厂模式的经典实现。Beans模块的主要作用是创建和管理Bean对象
  • Core模块:它提供了Spring框架的基本组成部分,包括IoC和DI功能
  • Context模块:它构建于Beans模块和Core模块基础上,它可以通过ApplicationContext接口提供上下文信息
  • SpEL模块:它是Spring3.0新增的模块,提供了SpEL表达式语言的支持。
  • web:web是分布在全世界的、基于HTTP通信协议的、存储在web服务器中的所有或相连接的超文本集
  • JS:JavaScript是一种嵌入在HTML文档中,具有跨平台、安全性,基于对象和事件驱动的解释型编程语言
  • CSS:级联样式表是一种用来表现HTML或XML等文件样式的计算机语言
  • HTML:超文本标记语言是标准通用标记语言下的一个应用,也是一种规范、标准。
  • JDBC:JDBC是一种访问数据库的技术标准,它是一种能通过Java语言访问数据库的应用程序接口。
  • Servelt:Servelt是一种用Java语言编写的服务器端语言,它担当客户请求与服务器响应的中间层。

填空题

Spring框架

  • Spring容器支持(XML)和(Properties)两种格式的配置文件
  • Spring的(bean)元素中包含一个(autowire)属性,可以通过设置(autowire)属性的值实现Bean的自动装配
  • Spring容器提供了两种基于XML的装配方式,(属性setter方法注入)和(构造方法注入)
  • Spring的作用域最常见的有两个,分别是(singleton)和(prototype)
  • Spring核心容器层的组成有四个,分别是,(Beans模块),(Core模块),(Context模块),(SpEL模块)
  • SpringMVC的跳转类型有三种,分别是,(返回值为void的跳转),(返回值为String类型的跳转),(返回值为ModelAndView的页面跳转)
  • SpringMVC的三大组件分别是,(处理器映射器),(处理器适配器),(视图解析器)
  • SpringMVC框架的组合注解一共有五个,分别是,(@GetMapping),(@PostMapping),(@PutMapping),(DeleteMapping),(@PatchMapping)
  • Spring的两大特性是(IoC)和(AOP)

Mybatis

  • Mybatis映射文件的根元素是(mapper)
  • Mybatis映射文件根元素mapper只有一个属性,它是(namespace)
  • Mybatis映射文件中常用的元素有(mapper)、(cache)、(cache-ref)、(resultMap)、(sql)、(insert)、(select)、(delete)、(update)
  • Mybatis的框架的核心对象主要有:(SqlSessionFactoryBuilder)、(SqlSessionFactory)、(SqlSession)
  • 动态SQL常用元素有(《if》)、(《choose》(《when》、《otherwise》))、(《where》)、(《trim》)、(《set》)、(《foreach》)
  • Mybatis常用注解有(@Insert)、(@Select)、(@Update)、(@Delete)、(@Param)

Spring的两大特性及其含义

IOC就是典型的工厂模式,通过sessionfactory去注入实例。

AOP就是典型的代理模式的体现。

IoC

IoC,英文全称Inversion of Control,意为控制反转。

在 使用Spring框架后,对象的实例不再由调用者来创建,而是由Spring的IoC容器来创建,IoC容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。这样,控制权由应用代码转到了IoC容器,控制权发生了反转,这就是Spring的控制反转。

AOP

AOP,英文全称Aspect-Oriented Programming,意为面向切面编程。

AOP主张将程序中相同的业务逻辑进行横向隔离,并将重复的业务逻辑抽取到一个独立的模块中,以达到提高程序可重用性和开发效率的目的。

Spring的自动装配机制

Spring容器支持XML和Properties两种格式的配置文件,在实际开发中,最常用的是XML格式的配置文件。XML是标准数据传输和存储格式,方便查看和操作数据。在Spring中,XML配置文件的根元素是,元素包含子元素,每个<bean子元素可以定义一个Bean,通过元素将Bean注册到Spring容器中。

自动装配

Spring的bean元素中包含一个autowire属性,可以通过设置autowire属性的值实现Bean的自动装配。

属性值 描述
default(默认值) 由的上级元素的default-autowire属性值确定。
byName 根据元素id属性的值自动装配。
byType 根据元素的数据类型(Type)自动装配,如果一个Bean的数 据类型,兼容另一个Bean中的数据类型,则自动装配。
constructor 根据构造函数参数的数据类型,进行byType模式的自动装配。
no 默认值,不使用自动装配,Bean依赖必须通过元素或ref属性定义。

基于XML的装配

在基于XML的装配就是读取XML配置文件中的信息完成依赖注入,Spring容器提供了两种基于XML的装配方式,属性setter方法注入和构造方法注入。

属性setter方法注入

属性setter方法注入要求一个Bean必须满足以下两点要求:

  • Bean类必须提供一个默认的无参构造方法
  • Bean类必须为需要注入的属性提供对应的setter方法

构造方法注入

使用构造方法注入时,在配置文件里,需要使用元素的子元素来定义构造方法的参数,例如,可以使其value属性来设置该参数的值。

  • 基于注解的装配

在Spring中,使用XML配置文件可以实现Bean的装配工作,但在实际开发中如果Bean的数量比较多,会导致XML文件过于臃肿,给后期维护和升级带来一定的困难。为解决此问题,Spring提供了注解,通过注解也可以实现Bean的装配。

基于注解的装配

Spring的常用注解

注解 描述
@Component 指定一个普通的Bean,可以作用在任何层次。
@Controller 指定一个控制器组件Bean,用于将控制层的类标识为Spring中的Bean,功能上等 同于@Component。
@Service 指定一个业务逻辑组件Bean,用于将业务逻辑层的类标识为Spring中的Bean,功 能上等同于@Component。
@Repository 指定一个数据访问组件Bean,用于将数据访问层的类标识为Spring 中的Bean,功 能上等同于@Component。
@Scope 指定Bean实例的作用域。
@Value 指定Bean实例的注入值。
注解 描述
@Autowired 指定要自动装配的对象。
@Resource 指定要注入的对象。
@Qualifier 指定要自动装配的对象名称,通常与@Autowired联合使用。
@PostConstruc t 指定Bean实例完成初始化后调用的方法。
@PreDestroy 指定Bean实例销毁前调用的方法

下面是基于注解装配的例子:

  • 定义实体类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @Component("user")
    @Scope("singleton")
    public class User {
    @Value("1")
    private int id;
    @Value("张三")
    private String name;
    @Value("123")
    private String password;
    // 省略getter/setter方法和toString()方法
    }
  • 定义dao层:创建UserDao接口作为数据访问层接口,并在UserDao接口中声明save()方法用于查询User实体类的对象信息。

    1
    2
    3
    4
    package com.hnust.dao;
    public interface UserDao {
    public void save();
    }
  • 实现dao层:创建UserDaoImpl作为UserDao的实现类,并在UserDao类中实现UserDao接口中的save()方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Repository("userDao")
    public class UserDaoImpl implements UserDao {
    public void save(){
    ApplicationContext applicationContext=new
    ClassPathXmlApplicationContext("applicationContext.xml");
    User user=(User) applicationContext.getBean("user");
    System.out.println(user);
    System.out.println("执行UserDaoImpl.save()");
    }
    }
  • 定义service层:创建UserService接口作为业务逻辑层的接口,并在UserService接口中定义save()方法。

    1
    2
    3
    4
    package com.hnust.service;
    public interface UserService {
    public void save();
    }
  • 实现service层:创建UserServiceImpl作为UserService的实现类,并在UserServiceImpl中实现UserService接口中的save()方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Service("userService")
    public class UserServiceImpl implements UserService {
    //使用@Resource注解注入UserDao
    @Resource(name="userDao")
    private UserDao userDao;
    public void save(){
    this.userDao.save();
    System.out.println("执行UserServiceImpl.save()");
    }
    }
  • 定义controller层:创建UserController类作为控制层。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Controller
    public class UserController {
    //使用@Resource注解注入UserService
    @Resource(name="userService")
    private UserService userService;
    public void save(){
    this.userService.save();
    System.out.println("执行UserController.save()");
    }
    }

Spring核心容器层组成

Spring核心容器模块在Spring的功能体系中起着支撑性作用,是其他模块的基石。核心容器层主要由Beans模块、Core模块、Context模块和SpEL模块组成。

核心容器模块各模块组成

  • Beans模块。它提供了BeanFactory类,是工厂模式的经典实现。Beans模块的主要作用是创建和管理Bean对象。
  • Core模块。它提供了Spring框架的基本组成部分,包括IoC和DI功能。
  • Context模块。它构建于Beans模块和Core模块之上,它可以通过ApplicationContext接口提供上下文信息。
  • SpEL模块。它是Spring3.0新增的模块,提供了SpEL表达式语言的支持,SpEL表达式语言是一个在程序运行时支持操作对象图的表达式语言。

Spring Bean的作用域

Bean的生命周期是指Bean的实例被创建、初始化和销毁的过程。在Bean的两种作用域singleton和prototype中,Spring容器对Bean的生命周期的管理是不同的。在singleton作用域中,Spring容器可以管理Bean的生命周期,控制着Bean的创建,初始化和销毁。在prototype作用域中,Spring容器只负责创建Bean的实例,不会管理其生命周期。

singleton作用域

当Bean是singleton作用域时,Spring容器只为Bean创建一个实例,该实例可以重复使用。Spring容器管理Bean的生命周期,控制着Bean的创建,初始化和销毁。singleton作用域可以避免反复创建和销毁实例造成的资源消耗。

prototype作用域

当Bean是prototype作用域时,每次对Bean时都会创建一个新的Bean实例,Spring创建Bean实例而不再管理其生命周期。

Spring MVC框架组合注解

Spring MVC在三层架构中的位置

Spring MVC组合注解:

  • @GetMapping:匹配GET方式的请求。

  • @PostMapping:匹配POST方式的请求。

  • @PutMapping:匹配PUT方式的请求。

  • @DeleteMapping:匹配DELETE方式的请求。

  • @PatchMapping:匹配PATCH方式的请求。

@GetMapping用法示例:

接下来以@GetMapping为例讲解组合注解的用法,@GetMapping是 @RequestMapping(method = RequestMethod.GET)的缩写,使用组合注解替代 @RequestMapping注解,可以省略method属性,从而简化代码。@GetMapping用 法示例代码如下所示。

1
2
3
4
@GetMapping(value="/firstController")
public void sayHello(){
...
}

那么什么是 @RequestMapping注解呢?

@RequestMapping注解用于建立请求URL和Handler(处理器)之间的映射关系, 该注解可以标注在方法上和类上。

@RequestMapping注解的使用

  • 当@RequestMapping注解标注在方法上时,该方法就成了一个可以处理客户端请求 的Handler(处理器),它会在Spring MVC接收到对应的URL请求时被执行。Handler在浏 览器中对应的访问地址,由项目访问路径+处理方法的映射路径共同组成。

    创建FirstController类,在类中创建sayHello()方法,用来处理客户端请求。

    1
    2
    3
    4
    5
    6
    7
    @Controller
    public class FirstController {
    @RequestMapping(value="/firstController")
    public void sayHello(){
    System.out.println("hello Spring MVC");
    }
    }
  • 当@RequestMapping注解标注在类上时,@RequestMapping的value属性值相当 于本处理器类的命名空间,即访问该处理器类下的任意处理器都需要带上这个命名空间。 @RequestMapping标注在类上时,其value属性值作为请求URL的第一级访问目录。当处 理器类和处理器都使用@RequestMapping注解指定了对应的映射路径,处理器在浏览器中 的访问地址,由项目访问路径+处理器类的映射路径+处理器的映射路径共同组成。

    接下来通过一个案例演示@RequestMapping注解标注在类上的使用。

    1
    2
    3
    4
    5
    6
    7
    8
    @Controller
    @RequestMapping(value="/springMVC")
    public class FirstController {
    @RequestMapping(value="/firstController")
    public void sayHello(){
    System.out.println("hello Spring MVC");
    }
    }

    说句人话,当@RequestMapping注解标注在类上时,相当于所有请求前面都有了个共同的前缀,当@RequestMapping注解标注在方法上时,它要跟在@RequestMapping注解标注在类上的value后面,是个小弟。

SpringMVC页面跳转类型

返回值为void类型的页面跳转到默认页面

当Spring MVC方法的返回值为void类型,方法执行后会跳转到默认的页面。默 认页面的路径由方法映射路径和视图解析器中的前缀、后缀拼接成,拼接格式为“前缀 +方法映射路径+后缀”。如果Spring MVC的配置文件中没有配置视图解析器,则会 报HTTP Status 500错误。

创建一个页面跳转类PageController,在PageController类中定义方法 showPageByVoid(),用于测试Spring MVC方法返回值为void的页面跳转。

1
2
3
4
5
6
7
@Controller
public class PageController {
@RequestMapping("/register")
public void showPageByVoid(){
System.out.println("showPageByVoid running");
}
}

上述代码的showPageByVoid()方法将会处理URL为register的请求, showPageByVoid()方法中没有返回值,只有一行打印输出字符串的代码。

返回值为String类型的页面跳转-不带数据

修改文件PageController.java,新增showPageByString()方法,用于测试返回值 为String类型的页面跳转,showPageByString()方法的实现代码如下所示

1
2
3
4
5
6
@Controller
public class PageController {
@RequestMapping("/register")
public String showPageByString() {
System.out.println("showPageByString running");}
}

跳转页面

访问地址后,执行了showPageByString()方法,方法执行后成 功跳转到WEB-INF文件夹下的register.jsp页面。如果此时注释掉Spring MVC配置文件springmvc.xml中的视图解析器,在浏览器中访问showPageByString()方法,请求会转发到映射路径为 register对应的showPageByVoid()方法中。

当方法的返回值为普通的字符串时,Spring MVC在方法执行后会默认以转发的方式响应给 客户端。除了这种默认的转发方式,还可以返回指定前缀的字符串,来设定处理器执行后对请求 进行转发还是重定向,设定转发和重定向的字符串格式如下所示。

  • forward:需要转发到的资源路径

  • redirect:需要重定向到的资源路径

修改文件PageController.java,新增showPageByForward()方法和 showPageByRedirect()方法,分别用于测试方法执行后转发和重定向的页面跳转。

1
2
3
4
5
6
7
8
@RequestMapping("/showPageByForward")
public String showPageByForward() {
System.out.println("showPageByForward running");
return "forward:orders.jsp"; }
@RequestMapping("/showPageByRedirect")
public String showPageByRedirect() {
System.out.println("showPageByRedirect running");
return "redirect:http://www.itheima.com"; }

跳转页面

在浏览器中访问访问地址 http://localhost:8080/chapter12/showPageByForward。访问地址后,执行了 showPageByForward()方法,方法执行后转发到项目的orders.jsp页面

在浏览器中访问地址http://localhost:8080/chapter12/showPageByRedirect。 访问后,浏览器页面进行跳转,跳转的页面如图所示。

跳转页面

访问地址后执行了 showPageByRedirect()方法,方法执行后重定向到黑马程序员的官网。需要注意的是,方法返回的 字符串一旦添加了“forward:”或“redirect:”前缀,那么视图解析器不再会为方法返回值拼接前 缀和后缀了。

返回值为String类型的页面跳转-携带数据

接下来通过一个案例演示携带数据的页面转发,该案例使用HttpServletRequest类型形参和 Model类型形参进行数据传递,案例具体实现步骤如下。

修改文件PageController.java,新增showPageByRequest()方法和 showPageByModel()方法,showPageByRequest()方法使用HttpServletRequest传 递数据,showPageByModel()方法使用Model传递数据,两个方法都使用字符串指 定跳转的页面。

1
2
3
4
5
6
7
// 只展示了showPageByRequest()方法
@RequestMapping("/showPageByRequest")
public String showPageByRequest(HttpServletRequest request) {
System.out.println("showPageByRequest running");
request.setAttribute("username","request");
return "register";
}

修改文件User.java,在register.jsp的表单中添加value属性,用于接收转发传递过 来的数据

1
2
3
4
5
6
7
8
9
10
<%@ page language="java" contentType="text/html;
charset=UTF-8" pageEncoding="UTF-8"%>
<html><!-- 只显示了form表单的内容-- ><body>
<form action="${pageContext.request.contextPath }/registerUser" >
用户名:<input type="text" name="username"
value="${username}" /><br />
密&nbsp;&nbsp;&nbsp;码:<input type="text"
name="password" value="${user.password}" /><br />
<input type="submit" value="注册"/></form></body>
</html>

在浏览器中访问地址 http://localhost:8080/chapter12/showPageByRequest。访问后,浏览器页面进行跳转,跳转的页面如图所示。

页面跳转

访问地址后执行了 showPageByRequest()方法,方法执行后HttpServletRequest中的username转发到register.jsp页 面中。

在浏览器中访问地址http://localhost:8080/chapter12/showPageByModel。访 问后,浏览器页面进行跳转,跳转的页面如图所示。

页面跳转

访问地址后执行了 showPageByModel()方法,方法执行后,Model中的username和user对象转发到register.jsp页面。

返回值为ModelAndView类型的页面跳转

使用方法的返回值可以设定跳转的逻辑视图名称,使用Model等对象实现页面跳 转时传输数据。除此之外,Spring MVC还提供了兼顾视图和数据的对象 ModelAndView,ModelAndView对象包含视图相关内容和模型数据两部分,其中视 图相关的内容可以设置逻辑视图的名称,也可以设置具体的View实例;模型数据则会 在视图渲染过程中被合并到最终的视图输出。

接下来通过一个案例演示返回值为ModelAndView类型的页面跳转,案例具体实现步骤如下

修改文件PageController.java,新增showModelAndView()方法,在 showModelAndView()方法中使用ModelAndView封装数据和视图,完成页面跳转 时传递数据。

1
2
3
4
5
6
7
8
9
@RequestMapping("/showModelAndView")
public ModelAndView showModelAndView() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("username","heima");
User user = new User(); user.setPassword("password");
modelAndView.addObject("user",user);
modelAndView.setViewName("register");
return modelAndView;
}

在浏览器中访问地址 http://localhost:8080/chapter12/showModelAndView。访问后,浏览器页面 进行跳转,跳转的页面如图所示。

页面跳转

访问地址后执行了showModelAndView()方法,方法执行后,添加的模 型数据都在register.jsp页面成功取出。

SpringMVC三大组件

处理器映射器

处理器映射器可以理解为一个Map,HandlerMapping负责根据 用户请求的URL找到Handler(处理器),Spring MVC提供了不同的映射器来实现不同 的映射方式。

处理器适配器

处理器适配器作用是根据处理器映射器找到的处理器 Handler 信息,去执行相关的 Handler。不同的处理器映射器映射出来的Handler对象是不一样的,不同的映射由不同 的适配器来负责解析。

视图解析器

视图解析器进行视图解析,首先将逻辑视图名解析成物理视图名,即具体的页面地 址,再生成View视图对象返回。

Spring MVC执行流程

执行流程

Mybatis映射文件

Mybatis的核心对象

  • SqlSessionFactoryBuilder
  • SqlSessionFactory
  • SqlSession

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder对象是线程安全的,它一旦被创建,在整个应用程序执行期间都会存在。如果我们多次创建同一个数据库的SqlSessionFactory对象,那么该数据库的资源将很容易被耗尽。通常每一个数据库只创建一个SqlSessionFactory对象,所以在构建SqlSessionFactory对象时,建议使用单例模式。

SqlSession

SqlSession是Mybatis框架中另一个重要的对象,它是应用程序与持久层之间执行交互操作的一个单线程对象,主要作用是执行持久化操作。类似于JDBC中的connection,SqlSession对象包含了执行SQL操作的方法,由于其底层封装了JDBC连接,所以可以直接使用SqlSession对象来执行已映射的SQL语句。

动态SQL(直接看代码即可)

动态SQL常用元素

元素 说明
判断语句,用于单条件判断
() 相当于Java中的switch…case…default语句,用于多条件判断
简化SQL语句中where的条件判断
可以灵活地去除多余的关键字
用于SQL语句的动态更新
循环语句,常用于in语句等列举条件中

条件查询操作

if元素的应用

在MyBatis中,元素是最常用的判断元素,它类似于Java中的if语句,主要用于 实现某些简单的条件判断。在实际应用中,我们可能会通过某个条件查询某个数据。例如, 要查找某个客户的信息,可以通过姓名或者年龄来查找客户,也可以不填写年龄直接通过 姓名来查找客户,还可以都不填写而查询出所有客户,此时姓名和年龄就是非必须条件。 类似于这种情况,在MyBatis中就可以通过元素来实现。

创建映射文件:创建映射文件CustomerMapper.xml,在映射文件中,根据客户姓名和年 龄组合条件查询客户信息,使用元素编写该组合条件的动态SQL。

1
2
3
4
5
6
7
<!– 该xml文件中只列出了if元素的动态SQL-->
<if test="username !=null and username !=‘’“>
and username like concat('%',#{username}, '%')
</if>
<if test="jobs !=null and jobs !=‘’“>
and jobs= #{jobs}
</if>

choose、when、otherwise元素

在使用元素时,只要test属性中的表达式为true,就会执行元素中的条件语句, 但是在实际应用中,有时只需要从多个选项中选择一个去执行。 例如下面的场景:“当客户名称不为空,则只根据客户名称进行客户筛选;当客户 名称为空,而客户职业不为空,则只根据客户职业进行客户筛选。当客户名称和客户职业 都为空,则要求查询出所有电话不为空的客户信息。” 针对上面情况,使用元素进行处理是不合适的。MyBatis提供了choose、when、otherwise元素进行处理,这三个元素往往组合在一起使用,作用相当于 Java语言中的if…else if…else。

在映射文件CustomerMapper.xml中,添加使用、、元素 执行上述情况的动态SQL。

1
2
3
4
5
6
7
8
9
10
<!-- 只展示三个组合元素的部分-->
<choose>
<when test="username !=null and username !=''">
and username like concat('%',#{username}, '%')
</when>
<when test="jobs !=null and jobs !=''">
and jobs= #{jobs}
</when>
<otherwise>and phone is not null</otherwise>
</choose>

where、trim元素

where、trim 使用场景:

在映射文件中,编写的SQL后面加入了“where 1=1”的条件的话,既保证了 where后面的条件成立,又避免了where后面第一个词是and或者or之类的关键字。 例如下面这条Mybatis拼接出的SQL语句是不正确的。

1
2
select * from t_customer where and username like concat('%',?,
'%') and jobs = #{jobs}

上述SQL语句中,where后直接跟的是and,这在运行时会报SQL语法错误,针对这 种情况,可以使用MyBatis提供的where元素和trim元素进行处理。

1
2
3
4
5
6
7
8
9
10
<select id="findCustomerByNameAndJobs"
parameterType="com.itheima.pojo.Customer"
resultType="com.itheima.pojo.Customer">
select * from t_customer
<where>
<if test="username !=null and username !=''">
and username like concat('%',#{username}, '%')</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}</if>
</where></select>

上述代码配置中,where元素会自动判断由组合条件拼装的SQL语句,只有where元素内的某一个或多个条件成立时,才会在拼接SQL中加入where关键字,否 则将不会添加;即使where之后的内容有多余的“AND”或“OR”,where元素也会自动将他们去除。

1
2
3
4
5
6
7
8
9
10
<select id="findCustomerByNameAndJobs"
parameterType="com.itheima.pojo.Customer"
resultType="com.itheima.pojo.Customer">
select * from t_customer
<trim prefix="where" prefixOverrides="and" >
<if test="username !=null and username !=''">
and username like concat('%',#{username}, '%')</if>
<if test="jobs !=null and jobs !=''">
and jobs= #{jobs}</if></trim>
</select>

上述配置代码中,trim元素的作用是去除一些多余的前缀字符串,它的prefix属 性代表的是语句的前缀(where),而prefixOverrides属性代表的是需要去除的前缀字 符串(SQL中的“AND”或“OR”)。

更新操作

在Hibernate框架中,如果想要更新某一个对象,就需要发送所有的字段给持久化 对象,然而在实际应用中,大多数情况下都是更新某一个或几个字段。如果更新的每一条 数据都要将其所有的属性都更新一遍,那么执行效率是非常差的。为了解决更新数据的效 率问题,MyBatis提供了set元素。set元素主要用于更新操作,它可以在动态SQL 语句前输出一个SET关键字,并将SQL语句中最后一个多余的逗号去除。set元素与if 元素结合可以只更新需要更新的字段。

在映射文件CustomerMapper.xml中,添加使用元素执行更新操作的动态SQL。

1
2
3
4
5
6
7
8
9
<update id="updateCustomerBySet”
parameterType="com.itheima.pojo.Customer">update t_customer
<set>
<if test="username !=null and username !=''">
username=#{username},</if>
<if test="jobs !=null and jobs !=''"> jobs=#{jobs},</if>
<if test="phone !=null and phone !=''">phone=#{phone},</if>
</set> where id=#{id}
</update>

复杂查询操作

foreach元素中的属性:

  • List类型:若入参为单参数且参数类型是一个List,collection属性值为list
  • 数组类型:若入参为单参数且参数类型是一个数组,collection属性值为array。
  • Map类型:若传入参数为多参数,就需要把参数封装为一个Map进行处理,collection属性值 为Map。若传入参数为多参数,就需要把参数封装为一个Map进行处理,collection属性 值为Map。

foreach元素迭代数组

在映射文件CustomerMapper.xml中,添加使用元素迭代数组执行批量查询操作 的动态SQL。

1
2
3
4
5
6
7
<select id="findByArray" parameterType="java.util.Arrays"
resultType="com.itheima.pojo.Customer">select * from t_customer where
id in
<foreach item="id" index="index" collection="array"
open="(" separator="," close=")"> #{id}
</foreach>
select>

foreach元素迭代List

在映射文件CustomerMapper.xml中,添加使用元素迭代List集合执行批量查询 操作的动态SQL。

1
2
3
4
5
6
7
8
<select id="findByList" parameterType="java.util.Arrays"
resultType="com.itheima.pojo.Customer">
select * from t_customer where id in
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>

foreach元素迭代Map

在映射文件CustomerMapper.xml中,添加使用元素迭代Map集合执行批量查询 操作的动态SQL。

1
2
3
4
5
6
7
<select id="findByMap" parameterType="java.util.Map"
resultType="com.itheima.pojo.Customer">
select * from t_customer where jobs=#{jobs} and id in
<foreach item="roleMap" index="index" collection="id" open="("
separator="," close=")"> #{roleMap}
</foreach>
</select>

Mybatis常用注解

@Select注解

示例:

  • 创建类:创建持久化类Worker,在Worker类中定义id、员工姓名、年龄、性别、工号等属 性以及属性对应的getter/setter方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Worker {
    private Integer id; private String name; private Integer age;
    private String sex;
    private String worker_id;
    // 省略getter/setter方法
    @Override
    public String toString() {
    return "Worker{" + "id=" + id + ", name=" + name +
    ", age=" + age + ", sex=" + sex + ", worker_id=" + worker_id + '}';
    }}
  • 编写查询方法

    1
    2
    3
    4
    5
    6
    7
    package com.itheima.dao;
    import com.itheima.pojo.Worker;
    import org.apache.ibatis.annotations.Select;
    public interface WorkerMapper {
    @Select("select * from tb_worker where id = #{id}")
    Worker selectWorker(int id);
    }
  • 加载配置文件::在核心配置文件mybatis-config.xml中的元素下引入 WorkerMapper接口,将WorkerMapper.java接口加载到核心配置文件中。

    1
    <mapper class="com.itheima.dao.WorkerMapper"/>

    @Insert注解

  • 添加注解:在WorkerMapper接口中添加向tb_worker数据表插入数据的方法 insertWorker(),并在方法上添加@Insert注解

    1
    2
    3
    @Insert("insert into tb_worker(name,age,sex,worker_id)"
    +"values(#{name},#{age},#{sex},#{worker_id})")
    int insertWorker(Worker worker);

    @Update注解

  • 添加注解:在WorkerMapper接口中添加更新tb_worker表中数据的方法,并在方法上添加 @Update注解。

    1
    2
    3
    @Update("update tb_worker set name = #{name},age = #{age} "
    +"where id = #{id}")
    int updateWorker(Worker worker);

    @Delete注解

  • 添加注解:在WorkerMapper接口中添加删除数据库中数据的方法,并在方法上添加 @Delete注解。

    1
    2
    @Delete("delete from tb_worker where id = #{id}")
    int deleteWorker(int id);

    @Param注解

下面通过一个案例演示@Param注解的使用,该案例要求根据员工的id和姓名查询员工信息, 案例具体实现步骤如下。

  • 添加注解:在WorkerMapper接口中添加多条件查询的方法。

    1
    2
    3
    4
    @Select("select * from tb_worker where id = #{param01}
    and name = #{param02}")
    Worker selectWorkerByIdAndName(@Param("param01") int id,
    @Param("param02") String name);

    Mybatis映射文件中常用元素

属性 说明
mapper 映射文件的根元素,该元素只有一个namespace属性(命名空间)。
cache 配置给定命名空间的缓存
cache-ref 从其他命名空间引用缓存配置。
resultMap 描述数据库结果集和对象的对应关系。
sql 可以重用的SQL块,也可以被其他语句使用。
insert 用于映射插入语句。
delete 用于映射删除语句。
update 用于映射更新语句。
select 用于映射查询语句。

mapper元素中namespace属性作用

namespace属性有两个作用:

  • 用于区别不同的mapper,全局唯一
  • 绑定DAO接口,即面向接口编程。当namespace绑定某一接口之后,可以不用写该接口的实现类,Mybatis会通过接口的全限定名查找到对应的mapper配置来执行SQL语句,因此namespace的命名必须跟接口同名。

mapper元素如何区别不同的XML文件

在不同映射文件中,mapper元素的子元素的id可以相同,Mybatis通过mapper元素的namespace属性值和子元素id联合区分不同的Mapper.xml文件。接口中的方法与映射文件中SQL语句id一一对应。