SSM 整合

article/2025/10/28 2:08:42

目录

  • 第六章 SSM 整合
    • 导图
    • 第一节 Spring 和 Mybatis 整合
      • 1、思路
      • 2、Mybatis-Spring技术
      • 3、总体 SSM 整合所需依赖
      • 4、配置数据源
        • ①创建 jdbc.properties
        • ②加入日志配置文件
        • ③创建 Spring 配置文件
        • ④创建 junit 测试类
      • 5、配置 SqlSessionFactoryBean
        • ①创建 Mybatis 全局配置文件
        • ②创建模型
        • ③创建Mapper接口
        • ④创建Mapper配置文件
        • ⑤配置 SqlSessionFactoryBean
          • [1]风格一:保留 Mybatis 全局配置文件
          • [2]风格二:彻底舍弃 Mybatis 全局配置文件
        • ⑥配置 Mapper 接口扫描器
          • [1]方式一:使用扫描器
          • [2]方式二:使用 mybatis-spring 名称空间
        • ⑦测试
      • 6、加入声明式事务
        • ①配置事务管理器
        • ②测试
          • [1]创建 Service 组件
          • [2]配置自动扫描的包
          • [3]测试
    • 第二节 Spring 和 SpringMVC 整合
      • 1、本质
      • 2、web.xml配置
      • 3、SpringMVC 配置
      • 4、创建组件
      • 5、页面操作
        • ①首页超链接
        • ②显示数据的页面
    • 第三节 分页
      • 1、提出问题
      • 2、分页的概念
        • ①分页本身的概念
        • ②分页的细节
      • 3、实现分页的基本逻辑
        • ①物理分页
        • ②逻辑分页
          • [1]需求
          • [2]总页数计算方式
          • [3]页码的合理化
        • ③分页执行流程
      • 4、Mybatis 的分页插件
        • ①依赖
        • ②配置
      • 5、实现分页功能
        • ①首页超链接
        • ②handler 方法
        • ③service 方法
        • ④页面展示
          • [1]显示数据
          • [2]显示翻页导航栏
        • ⑤打印的 SQL 语句
      • 6、为什么是 PageInfo 而不是 Page
        • ①List接口的具体实现
        • ②提出问题
        • ③PageHelper 非侵入式的体现
    • 第四节 增删改操作
      • 1、设计 URL 地址
      • 2、删除操作
        • ①创建超链接
        • ②handler 方法
        • ③service 方法
        • ④mapper 方法
        • ⑤SQL 语句
      • 3.1、保存操作:前往表单页面
        • ①创建超链接
        • ②创建 view-controller
        • ③创建视图页面
      • 3.2、保存操作:提交表单
        • ①handler 方法
        • ②service 方法
        • ③mapper 方法
        • ④SQL 语句
      • 4.1、更新操作:前往表单页面
        • ①创建超链接
        • ②handler 方法
        • ③service 方法
        • ④mapper 方法
        • ⑤SQL 语句
        • ⑥创建页面视图
      • 4.2、更新操作:提交表单
        • ①handler 方法
        • ②service 方法
        • ③mapper 方法
        • ④SQL 语句

第六章 SSM 整合

导图

在这里插入图片描述

第一节 Spring 和 Mybatis 整合

1、思路

在这里插入图片描述

2、Mybatis-Spring技术

官方介绍

相关技术之间版本匹配说明:

在这里插入图片描述

Mybatis-Spring 的依赖:

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version>
</dependency>

3、总体 SSM 整合所需依赖

<!-- SpringMVC -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.3.1</version>
</dependency><!-- Spring 持久化层所需依赖 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>5.3.1</version>
</dependency><!-- 日志 -->
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency><!-- ServletAPI -->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope>
</dependency><!-- Spring5和Thymeleaf整合包 -->
<dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf-spring5</artifactId><version>3.0.12.RELEASE</version>
</dependency><!-- Mybatis核心 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version>
</dependency><!-- MySQL驱动 -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.3</version>
</dependency><!-- 数据源 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.31</version>
</dependency><!-- junit5 -->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.7.0</version><scope>test</scope>
</dependency><!-- Spring 的测试功能 -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.3.1</version>
</dependency><!-- Mybatis 和 Spring 的整合包 -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.6</version>
</dependency>

4、配置数据源

①创建 jdbc.properties

jdbc.user=root
jdbc.password=atguigu
jdbc.url=jdbc:mysql://192.168.198.100:3306/mybatis-example
jdbc.driver=com.mysql.jdbc.Driver

②加入日志配置文件

在这里插入图片描述

③创建 Spring 配置文件

在这里插入图片描述

<!-- 加载外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置数据源 -->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="username" value="${jdbc.user}"/><property name="password" value="${jdbc.password}"/><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/>
</bean>

④创建 junit 测试类

@SpringJUnitConfig(locations = {"classpath:spring-persist.xml"})
public class SSMTest {@Autowiredprivate DataSource dataSource;Logger logger = LoggerFactory.getLogger(getClass());@Testpublic void testConn() throws SQLException {Connection connection = dataSource.getConnection();logger.debug(connection.toString());}}

5、配置 SqlSessionFactoryBean

①创建 Mybatis 全局配置文件

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!-- Mybatis全局配置 --><settings><!-- 将数据库表字段映射到驼峰式命名的Java实体类属性中 --><!-- 数据库表字段格式:单词_单词 --><!-- Java实体类属性:首字母小写的驼峰式命名 --><setting name="mapUnderscoreToCamelCase" value="true"/></settings></configuration>

②创建模型

public class Emp {private Integer empId;private String empName;private Double empSalary;

③创建Mapper接口

public interface EmpMapper {List<Emp> selectAll();}

④创建Mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- mapper是根标签。namespace属性是找到当前配置的依据 -->
<!-- 由于最理想的Mybatis使用方式是:通过Mapper接口调用接口方法,访问数据库 -->
<!-- 这样的理想方式要求:能够通过接口全类名找到Mapper配置 -->
<!-- 所以:我们就用Mapper接口的全类名来给namespace属性赋值 -->
<mapper namespace="com.atguigu.ssm.mapper.EmpMapper"><!-- List<Emp> selectAll(); --><select id="selectAll" resultType="Emp">select emp_id,emp_name,emp_salary from t_emp</select></mapper>

⑤配置 SqlSessionFactoryBean

[1]风格一:保留 Mybatis 全局配置文件
<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 指定 Mybatis 全局配置文件位置 --><property name="configLocation" value="classpath:mybatis-config.xml"/><!-- 指定 Mapper 配置文件位置 --><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!-- 装配数据源 --><property name="dataSource" ref="druidDataSource"/></bean>
[2]风格二:彻底舍弃 Mybatis 全局配置文件
<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 舍弃 Mybatis 全局配置文件,使用 configuration 属性 --><property name="configuration"><bean class="org.apache.ibatis.session.Configuration"><property name="mapUnderscoreToCamelCase" value="true"/></bean></property><!-- 舍弃 Mybatis 全局配置文件,使用 typeAliasesPackage 属性配置实体类所在包 --><property name="typeAliasesPackage" value="com.atguigu.ssm.entity"/><!-- 指定 Mapper 配置文件位置 --><property name="mapperLocations" value="classpath:mappers/*Mapper.xml"/><!-- 装配数据源 --><property name="dataSource" ref="druidDataSource"/></bean>

注意:上面两种方式如果并存,会抛出异常:

java.lang.IllegalStateException: Property ‘configuration’ and ‘configLocation’ can not specified with together

⑥配置 Mapper 接口扫描器

[1]方式一:使用扫描器
<!-- 配置 Mapper 接口类型的bean的扫描器 -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.atguigu.ssm.mapper"/>
</bean>
[2]方式二:使用 mybatis-spring 名称空间
<mybatis-spring:scan base-package="com.atguigu.ssm.mapper"/>
  • 作用:扫描mapper包下所有的接口,根据对应的xml,生成实现类
    在这里插入图片描述
    详细博客

⑦测试

@Autowired
private EmpMapper empMapper;@Test
public void testMybatis() {List<Emp> empList = empMapper.selectAll();for (Emp emp : empList) {logger.debug(emp.toString());}
}

6、加入声明式事务

①配置事务管理器

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 装配数据源 --><property name="dataSource" ref="druidDataSource"/>
</bean><!-- 开启基于注解的声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

②测试

[1]创建 Service 组件

在这里插入图片描述

@Service
public class EmpServiceImpl implements EmpService {@Autowiredprivate EmpMapper empMapper;@Override@Transactional(readOnly = true)public List<Emp> getAll() {return empMapper.selectAll();}
}
[2]配置自动扫描的包

在这里插入图片描述

<context:component-scan base-package="com.atguigu.ssm.service"/>
[3]测试
@Autowired
private EmpService empService;@Test
public void testTx() {List<Emp> empList = empService.getAll();for (Emp emp : empList) {System.out.println("emp = " + emp);}
}

第二节 Spring 和 SpringMVC 整合

1、本质

  • ContextLoaderListener:读取 spring-persist.xml
  • DispatcherServlet:读取 spring-mvc.xml

2、web.xml配置

<!-- ContextLoaderListener -->
<!-- 通过 context-param 指定 Spring 框架的配置文件位置 -->
<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-persist.xml</param-value>
</context-param><!-- 配置 ContextLoaderListener 监听器 -->
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><!-- DispatcherServlet -->
<servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping><!-- 需要注意两个 Filter 的顺序:字符集过滤器在前,转换请求方式过滤器在后 -->
<!-- CharacterEncodingFilter -->
<filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceRequestEncoding</param-name><param-value>true</param-value></init-param><init-param><param-name>forceResponseEncoding</param-name><param-value>true</param-value></init-param>
</filter>
<filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping><!-- HiddenHttpMethodFilter -->
<!-- HiddenHttpMethodFilter过滤器的作用是将form表单提交的POST请求转化为指定的标准请求(GET,、POST、 HEAD、OPTIONS、PUT、DELETE、TRACE)。
该过滤器的实现原理是:通过读取POST请求体中的"_method"属性值,将该属性值作为 HttpServletRequestWrapper.getMethod()的返回值。-->
<filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

3、SpringMVC 配置

<!-- SpringMVC 只扫描 handler 类所在的包 -->
<!-- Spring 和 SpringMVC 扫描各自负责的组件,扫描的范围没有重合的部分,直接避免了重复创建对象 -->
<context:component-scan base-package="com.atguigu.ssm.handler"/><!-- 配置 Thymeleaf 的视图解析器 -->
<bean id="thymeleafViewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"><property name="order" value="1"/><property name="characterEncoding" value="UTF-8"/><property name="templateEngine"><bean class="org.thymeleaf.spring5.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"><property name="prefix" value="/WEB-INF/templates/"/><property name="suffix" value=".html"/><property name="characterEncoding" value="UTF-8"/><property name="templateMode" value="HTML5"/></bean></property></bean></property>
</bean><!-- SpringMVC 注解驱动(标配) -->
<mvc:annotation-driven/><!-- 对于没有映射的请求直接转发放行,主要是静态资源 -->
<mvc:default-servlet-handler/><!-- 匹配请求路径直接前往视图,不经过 handler 方法 -->
<mvc:view-controller path="/" view-name="portal"/>
<mvc:view-controller path="/index.html" view-name="portal"/>

4、创建组件

在这里插入图片描述

@Controller
public class EmpHandler {@Autowiredprivate EmpService empService;@RequestMapping("/get/all")public String getAll(Model model) {// 1、查询数据List<Emp> empList = empService.getAll();// 2.存入模型model.addAttribute("empList", empList);return "emp-list";}}

5、页面操作

①首页超链接

在这里插入图片描述

<a th:href="@{/get/all}">显示全部数据</a>

②显示数据的页面

在这里插入图片描述

<table><tr><th>ID</th><th>NAME</th><th>SALARY</th></tr><tbody th:if="${#lists.isEmpty(empList)}"><tr><td colspan="3">抱歉!没有查询到数据!</td></tr></tbody><tbody th:if="${not #lists.isEmpty(empList)}"><tr th:each="emp : ${empList}"><td th:text="${emp.empId}">这里显示员工ID</td><td th:text="${emp.empName}">这里显示员工NAME</td><td th:text="${emp.empSalary}">这里显示员工SALARY</td></tr></tbody>
</table><a th:href="@{/}">回首页</a>

第三节 分页

1、提出问题

如果应用程序显示数据不分页,会有三个问题:

  • 用户查看数据非常不方便。
  • 所有数据不分冷热全部显示出来,冷数据白白占用存储空间,浪费内存。
  • 在服务器端查询全部数据占用内存很大,给整个系统增加了很大压力。

2、分页的概念

①分页本身的概念

把系统中要显示的数据分成较小的单元,每个单元作为『一页』显示给用户。每次访问服务器只查询一页数据。

分页的好处:

  • 用户体验较好。
  • 服务器端每次只查询一部分数据,内存压力减小。
  • 对冷数据减少查询的次数,据此对系统性能进行优化。

②分页的细节

在这里插入图片描述

3、实现分页的基本逻辑

①物理分页

具体数据库不同,分页语法有区别。下面我们以 MySQL 为例来说明。MySQL 的分页需要借助 LIMIT 子句来完成。

select emp_id,emp_name,emp_salary from t_emp limit 0,5; # 查询第一页数据
select emp_id,emp_name,emp_salary from t_emp limit 5,5; # 查询第二页数据
select emp_id,emp_name,emp_salary from t_emp limit 10,5;# 查询第三页数据

LIMIT 子句的公式:

limit (pageNo-1)*pageSize, pageSize每页条数

注意:在 SQL 的语法中,LIMIT 子句必须出现在 SQL 语句最后。

②逻辑分页

[1]需求

为了能够在页面上全面显示分页相关的细节数据,总页数需要计算得到。

[2]总页数计算方式

在这里插入图片描述

[3]页码的合理化

页码的有效范围:1~总页数。修正方式:

  • 用户输入的页码 < 1:将页码设定为第一页
  • 用户输入的页码 > 总页数:将页码设定为最后一页

③分页执行流程

  • 查询总记录数
  • 查询当前页数据
  • 根据总记录数和每页条数计算总页数
  • 在1~总页数之间修正页码
  • 封装上述所有数据,发送到页面显示

4、Mybatis 的分页插件

具体使用细节可以参考:官方文档

在这里插入图片描述

①依赖

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version>
</dependency>

②配置

<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">……<!-- 在 plugins 属性中配置 Mybatis 插件 --><property name="plugins"><array><bean class="com.github.pagehelper.PageInterceptor"><property name="properties"><props><!-- 设置 reasonable 为 true 表示将页码进行合理化修正。页码的有效范围:1~总页数 --><prop key="reasonable">true</prop><!-- 数据库方言:同样都是 SQL 语句,拿到不同数据库中,在语法上会有差异 --><!-- 默认情况下,按照 MySQL 作为数据库方言来运行 --><prop key="helperDialect">mysql</prop></props></property></bean></array></property></bean>

5、实现分页功能

①首页超链接

<a th:href="@{/get/page/1}">显示分页数据</a>

②handler 方法

@RequestMapping("/get/page/{pageNo}")
public String getPage(@PathVariable("pageNo") Integer pageNo, Model model) {// PageInfo 对象封装了和分页相关的所有信息PageInfo<Emp> pageInfo = empService.getPageInfo(pageNo);// 将 PageInfo 对象存入模型model.addAttribute("pageInfo", pageInfo);return "emp-page";
}

③service 方法

@Override
public PageInfo<Emp> getPageInfo(Integer pageNo) {// 1、确定每页显示数据的条数int pageSize = 5;// 2、设定分页数据:开启分页功能。开启后,后面执行的 SELECT 语句会自动被附加 LIMIT 子句,// 而且会自动查询总记录数PageHelper.startPage(pageNo, pageSize);// 3、正常执行查询List<Emp> empList = empMapper.selectAll();// 4、封装为 PageInfo 对象返回return new PageInfo<>(empList);
}

④页面展示

[1]显示数据
……<tr th:each="emp : ${pageInfo.list}">
……
[2]显示翻页导航栏
<span th:if="${pageInfo.hasPreviousPage}"><a th:href="@{/get/page/1}">首页</a><a th:href="@{/get/page/}+${pageInfo.prePage}">上一页</a>
</span><span th:each="navigator : ${pageInfo.navigatepageNums}"><!-- th:if 判断当前标签是否是当前页 --><!-- 如果不是当前页则显示超链接 --><a th:if="${navigator != pageInfo.pageNum}"th:href="@{/get/page/}+${navigator}"th:text="'['+${navigator}+']'"></a><!-- 如果是当前页则显示页码本身 --><span th:if="${navigator == pageInfo.pageNum}" th:text="'['+${navigator}+']'"></span>
</span><span th:if="${pageInfo.hasNextPage}"><a th:href="@{/get/page/}+${pageInfo.nextPage}">下一页</a><a th:href="@{/get/page/}+${pageInfo.pages}">最后一页</a>
</span><span th:text="${pageInfo.pageNum}+'/'+${pageInfo.pages}"></span>

⑤打印的 SQL 语句

在这里插入图片描述

6、为什么是 PageInfo 而不是 Page

①List接口的具体实现

当我们开启了分页功能后,查询一个 List 集合,实际返回的是:com.github.pagehelper.Page 类型。这个 Page 类继承了 ArrayList,所以也兼容 List 接口类型。

②提出问题

如果我们将 Page 类型的对象存入模型,转发到视图模板上显示数据,会存在一个问题:视图模板技术只承认这个对象是一个 List 集合,不识别 List 集合之外的其它属性

这一点在其他场合也需要注意:我们开发时尽量不要继承 ArrayList、HashMap 等类似的集合实现类。如果继承了,那么页面视图模板技术或其他表达式往往只能识别我们的对象是一个集合,而无法访问额外封装的其他属性。

所以 Page 对象需要封装为 PageInfo,让 list、pageNum 等等数据作为 PageInfo 对象的属性;PageInfo 本身并不是一个 List 类型的集合。

③PageHelper 非侵入式的体现

PageHelper.startPage(pageNo, pageSize);

开启分页功能,就在 SQL 语句后面附加 LIMIT 子句并查询总记录数;不开启就还是按照原样查询。分页功能对原有的 Mapper 接口、SQL 语句没有任何影响。这个效果可以称之为是非侵入式,也可以说是可插拔的。

第四节 增删改操作

1、设计 URL 地址

功能地址请求方式
删除/emp/{empId}/{pageNo}DELETE
前往新增页面/emp/addview-controller
提交新增表单/empPOST
前往更新页面/emp/{empId}/{pageNo}GET
提交更新表单/empPUT

2、删除操作

①创建超链接

在这里插入图片描述

<a th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}" @click="doConvert">删除</a>

②handler 方法

在这里插入图片描述

@DeleteMapping("/emp/{empId}/{pageNo}")
public String doRemove(@PathVariable("empId") Integer empId,@PathVariable("pageNo") Integer pageNo
) {// 执行删除empService.removeEmpById(empId);return "redirect:/get/page/" + pageNo;
}

③service 方法

在这里插入图片描述

@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void removeEmpById(Integer empId) {empMapper.deleteByPrimaryKey(empId);}

④mapper 方法

在这里插入图片描述

void deleteByPrimaryKey(Integer empId);

⑤SQL 语句

在这里插入图片描述

<!-- void deleteByPrimaryKey(Integer empId); -->
<delete id="deleteByPrimaryKey">delete from t_emp where emp_id=#{empId}
</delete>

3.1、保存操作:前往表单页面

①创建超链接

在这里插入图片描述

    <tr><td colspan="5"><a th:href="@{/emp/add}">前往添加数据的表单页面</a></td></tr>
</tbody>

②创建 view-controller

在这里插入图片描述

<mvc:view-controller path="/emp/add" view-name="emp-add-form"/>

③创建视图页面

在这里插入图片描述

<form th:action="@{/emp}" method="post">员工姓名:<input type="text" name="empName" /><br/>员工工资:<input type="text" name="empSalary" /><br/><button type="submit">保存</button>
</form>

3.2、保存操作:提交表单

①handler 方法

在这里插入图片描述

@PostMapping("/emp")
public String saveEmp(Emp emp) {// 执行保存empService.saveEmp(emp);// 为了在保存完成后直接显示新数据,直接前往最后一页// 通过 Integer.MAX_VALUE 获取一个非常大的数据,// 再结合配置 PageHelper 时指定的 reasonable 就可以直接前往最后一页return "redirect:/get/page/" + Integer.MAX_VALUE;
}

②service 方法

在这里插入图片描述

@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
@Override
public void saveEmp(Emp emp) {empMapper.insertEmp(emp);
}

③mapper 方法

在这里插入图片描述

void insertEmp(Emp emp);

④SQL 语句

在这里插入图片描述

<!-- void insertEmp(Emp emp); -->
<insert id="insertEmp">insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert>

4.1、更新操作:前往表单页面

①创建超链接

在这里插入图片描述

<a th:href="@{/emp/}+${emp.empId}+'/'+${pageInfo.pageNum}">更新</a>

②handler 方法

在这里插入图片描述

  • PathVariable自动将变量存入模型
  • @PathVariable 注解解析得到的数据会被自动存入模型,
    属性名就是注解中的变量名
@GetMapping("/emp/{empId}/{pageNo}")
public String toEditPage(@PathVariable("empId") Integer empId,// @PathVariable 注解解析得到的数据会被自动存入模型,// 属性名就是注解中的变量名@PathVariable("pageNo") Integer pageNo,Model model
) {// 执行查询Emp emp = empService.getEmpById(empId);// 将实体类对象存入模型model.addAttribute("emp", emp);return "emp-edit-form";
}

③service 方法

在这里插入图片描述

@Override
@Transactional(readOnly = true)
public Emp getEmpById(Integer empId) {return empMapper.selectByPrimaryKey(empId);
}

④mapper 方法

在这里插入图片描述

Emp selectByPrimaryKey(Integer empId);

⑤SQL 语句

在这里插入图片描述

<!-- Emp selectByPrimaryKey(Integer empId); -->
<select id="selectByPrimaryKey" resultType="Emp">select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}
</select>

⑥创建页面视图

在这里插入图片描述

<form th:action="@{/emp}" method="post"><!-- 附带表单隐藏域:将 POST 请求转换为 PUT 请求 --><input type="hidden" name="_method" value="PUT" /><!-- 附带表单隐藏域:实体类的 id --><input type="hidden" name="empId" th:value="${emp.empId}" /><!-- 附带表单隐藏域:来源页的页码 --><input type="hidden" name="pageNo" th:value="${pageNo}" /><!-- 常规表单项回显 -->员工姓名:<input type="text" name="empName" th:value="${emp.empName}" /><br/>员工工资:<input type="text" name="empSalary" th:value="${emp.empSalary}" /><br/><button type="submit">更新</button>
</form>

4.2、更新操作:提交表单

①handler 方法

在这里插入图片描述

@PutMapping("/emp")
public String updateEmp(Emp emp, @RequestParam("pageNo") Integer pageNo) {// 执行更新empService.updateEmp(emp);// 重定向到分页页面return "redirect:/get/page/" + pageNo;
}

②service 方法

在这里插入图片描述

@Override
@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)
public void updateEmp(Emp emp) {empMapper.updateEmpByPrimaryKey(emp);
}

③mapper 方法

在这里插入图片描述

void updateEmpByPrimaryKey(Emp emp);

④SQL 语句

在这里插入图片描述

<!-- void updateEmpByPrimaryKey(Emp emp); -->
<update id="updateEmpByPrimaryKey">update t_emp set emp_name=#{empName},emp_salary=#{empSalary}where emp_id=#{empId}
</update>

http://chatgpt.dhexx.cn/article/XVxWqvVf.shtml

相关文章

SSM整合Vue

昨日知识点总结 今日总结 文章目录 一.昨日知识 1.表单验证2.上传组件3.时间插件4.ElementUI简介 二.今日总结 1.页面静态化 通过html页面&#xff0c;制作展示所有制作添加页面 制作修改页面以及批量删除制作分页制作多条件查询 一、昨日重点复习 1.表单验证 在vue中使用rule…

SSM整合过程梳理

文章目录 前言一.SSM整合流程二.整合配置2.1添加依赖2.2创建项目包结构2.3创建SpringConfig配置类2.4创建JdbcConfig配置类2.5创建MybatisConfig配置类2.6创建jdbc.properties2.7创建SpringMVC配置类2.8创建Web项目入口配置类 三.功能模块3.1创建模型类3.2编写Dao接口3.3编写Se…

ssm整合详解

最近做项目用到了ssm,虽然以前用过ssm但这段时间发现&#xff0c;用过不代表就会了&#xff0c;即使以前用过&#xff0c;但现在要搭一个ssm框架不看教程还是很难&#xff0c;最基本的maven仓库需要哪些坐标都搞不清楚&#xff0c;所以今天打算写篇博客梳理一下。 一.基础梳理…

SSM整合分页插件

目录 一.环境配置 1.分页插件依赖 2.在Mybatis里面配置的内容 二.使用分页插件 1.在ServiceImpl层开启分页插件&#xff08;即查询数据库前开启&#xff09; 2.控制器方法 3.jsp页面进行整理 4.效果 5. 样式 6.常用的数据说明 一.环境配置 1.分页插件依赖 <depend…

SSM整合总结

这几天学完spring&#xff0c;springMVC&#xff0c;mybatis后&#xff0c;这两天试着去整合ssm&#xff0c;整合过程并不顺利&#xff0c;一是基础知识有的忘了&#xff0c;细节不能把握住&#xff0c;造成各种报错.看了各种视频&#xff0c;翻阅各种文章&#xff0c;多多少少…

SSM整合shiro

1.完成ssm整合shiro 企业中老项目还在使用ssm框架。 准备数据库 数据结构 张三 -user:query user:add user:update user:delete 李四 ---》user:query user:add user:update 王五-----》user:query user:export 搭建ssm的环境 &#xff08;1&#xff09;创建一个maven的web工…

SSM整合

1、ssm整合原理 SSM框架是spring MVC &#xff0c;spring和mybatis框架的整合&#xff0c;是标准的MVC模式&#xff0c;将整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层。 使用spring MVC负责请求的转发和视图管理 spring实现业…

SSM整合,手把手教程,详解思路讲解

前言 一&#xff0c;工程创建 1.新建Maven项目&#xff0c;项目架构增加web支持 2.Maven本地仓库配置 3.集成Tomcat&#xff0c;搭建web环境 二&#xff0c;导入依赖 三&#xff0c;配置文件编写 1.web环境配置文件 2.spring整合环境配置文件 2.1 controller层(spring…

SSM整合完整流程讲解

目录 一、SSM整合说明 1、各个框架担任的角色 2、两个Ioc容器的创建顺序 1&#xff09;SpringMVC中IOC容器的创建时间 2&#xff09;Spring中IOC容器的创建时间 3&#xff09;Spring提供的监听器ContextLoaderListener 二、SSM整合步骤 1、准备工作 1&#xff09;导入…

Unresolved Dependencies

在Android Studio的开发中&#xff0c;在软件中集成了ButterKnife插件&#xff0c;另外需要集成ButterKnife的jar包。因为本地没有现成的&#xff0c;所以在module的build.gradle文件中添加了如下代码&#xff1a; compile com.jakewharton:butterknife:7.0.1 结果报了如下错误…

Pycharm 出现Unresolved reference ‘‘ 错误的解决方法 --- 亲测有效

在用Pycharm写项目的时候的时候碰到一个很无语的问题 路径明明没有问题&#xff0c;运行也没有出错&#xff0c;但就是爆红&#xff0c;逼死强迫症啊。。。 多方查找最后解决了。步骤如下&#xff1a; File–>Settings–>Project Structure–>找到问题目录–>Sou…

PyCharm错误提示- Unresolved reference 的解决

使用PyCharm加载工程时,发生解析错误 原本这个工程是可以通过 python manange.py runserver 方式运行的,说明文件是正常的。关键在于PyCharm环境的问题。 查找了半天,安装一些网上的解决方式,尝试了以下几种方式: 1,修改忽略文件 File –>Settings –>Editor –…

Goland 提示 Unresolved reference 错误解决

之前一直正常的项目&#xff0c;莫名其妙的 database/sql 包下的方法、结构体等等IDE都无法识别&#xff0c;出现一堆Unresolved reference错误提示&#xff0c;但包导入路径可以正确定位&#xff0c;而且项目运行也正常&#xff0c;其他包都正常&#xff0c;另一个项目下同样使…

error LNK2019: unresolved external symbol

error LNK2019: unresolved external symbol&#xff1a;链接器找不到所需要的东西 此时ctrlF7进行编译&#xff0c;没有报错&#xff0c;在这个程序中调用的是Log函数&#xff0c;我们实际上并没有这个函数&#xff0c; 我们有的函数是Logr函数&#xff0c;在编译过程中编译器…

Unresolved reference ‘matplotlib‘解决方法

首先打开最左边的file-settings 然后点这个添加 找想添加的 最后点最下面的install Package 就可以啦

快速解决Pycharm中unresolved reference

在用Pycharm时老是报红&#xff0c;虽然不影响运行&#xff0c;但是真的很不好看。 如下&#xff1a; 根据网上大部分教程设置source root&#xff0c;设置之后还是没有变化。 然后我发现了这个东西&#xff0c;真的是立即生效&#xff0c;就是不知道改了之后有没有什么后遗症…

解决unresolved symbol _RamfuncsLoadEnd

问题描述 移植大佬的文件之后&#xff0c;发现报错 问题解决 添加F28335.cmd到工程中

Redisson cannot use an unresolved DNS server address问题解决

概述 本文记录Mac IDEA开发&#xff0c;公司 远程办公时遇到的两个问题&#xff0c;记录一下。 问题 cannot use an unresolved DNS server address: [fe80::1%en0]:53 在家里&#xff0c;连上公司的VPN后&#xff0c;即可打开公司内网&#xff0c;远程办公。一切正常。某…

解决模块Unresolved Link问题

修改内容为下面的&#xff0c;请复制以下内容&#xff08;图中大小写有误&#xff09;&#xff01;&#xff01; Solver_SF/CarSim S-Function 此时就可以修改Simfile name了

c语言1 unresolved externals,出现了 unresolved external symbol _main和1 unresolved externals这是什么问题?...

满意答案 nyjspj 2014.01.18 采纳率&#xff1a;53% 等级&#xff1a;12 已帮助&#xff1a;5918人 {} 数量不匹配 #include #include "process.h" #include "stdio.h" #include "sqstack.h" template void convert(T n,T m) { T e; char c; …