Spring + Spring MVC + MyBatis 整合开发
maven
Maven 的翻译为 “专家”、“行家” ,是一个跨平台的项目管理工具。
- 主要用于:基于 Java 平台的项目(Maven 本身也是 Java 编写的)的构建、依赖包管理和项目信息管理。
Maven 主要用处一:相同的项目结构
Maven 提供了一种标准的项目目录结构,测试命名规则等项目的最佳实践方案,统一了不同项目的学习成本(约定大于配置)
新建一个默认的maven项目,会出现以下结构

- 有一个 pom.xml 用于维护当前项目所依赖的 jar 包
- 所有的 Java 代码都放在 src/main/java 目录下
- 所有的测试代码都放在 src/test/java 目录下
Maven 主要用处二:统一维护 jar 包
Maven能提供一种项目的依赖配置,配置好的项目,Maven 能自动的从 Maven 的中央仓库中帮我们下载并管理项目依赖的 jar 包,并且还能自动的管理这些 jar 包依赖的其他 jar 包
配置文件内容
在【pom.xml】文件中声明依赖的 jar 包:
<dependencies>
<!--Junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!--Servlet - JSP -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
</dependencies>Maven资源过滤设置
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>建立基本结构和配置框架

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>
<typeAliases>
<package name="com.luo.pojo"/>
</typeAliases>
<mappers>
<mapper resource="com/luo/dao/BookMapper.xml"/>
</mappers>
</configuration>spring配置文件:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd ">
<import resource="classpath:spring-dao.xml"/>
<import resource="classpath:spring-service.xml"/>
<import resource="classpath:springmvc.xml"/>
</beans>Mybatis层编写
创建一个存放货物数据的数据库表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` int(0) NOT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`price` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
`quantity` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES (1, '电视机', '5000', '100');
INSERT INTO `goods` VALUES (2, '电冰箱', '4000', '200');
INSERT INTO `goods` VALUES (3, '空调', '3000', '300');
INSERT INTO `goods` VALUES (4, '赛克斯', '666', '666');
INSERT INTO `goods` VALUES (5, '22', '22', '33');
INSERT INTO `goods` VALUES (7, 'r', 'r', 'r');
SET FOREIGN_KEY_CHECKS = 1;数据库配置文件:database.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=true&useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456IDEA关联数据库
点击idea右侧的Database,之后选择左上角的 + 号鼠标移到Data Source(数据源)上,右侧弹出列表,选择数据库

点击打开配置

输入
Database: 数据库名称
User: 用户名
Password: 密码
如果左下角有 Download missing driver files 需要点击Download下载资源,之后点击Test Connection测试连接是否成功,如果成功点击OK会弹出显示,不成功需要自己修改配置

应用并确定,数据库连接成功

附:工具的作用

1.

同步:无论是使用其他客户端或者Java代码对数据库进行了修改,可以点击按钮对数据做一个实时的同步,更新内容
2.

编辑:就是配置信息的模块,可以进行修改、增加、删除等操作
3.

断开:断开与数据库的连接
4.

显示表:选中表点击就会将表的内容显示在idea中
5.
编辑:修改创建的表的sql语句
编写数据库对应的实体类 com.luo.pojo.Goods
不使用插件
package com.luo.pojo;
public class Goods {
//实体类
private int goodsID;
private String goodsName;
private String goodsPrice;
private String goodsQuantity;
//toString
@Override
public String toString() {
return "Goods{" +
"goodsID=" + goodsID +
", goodsName='" + goodsName + '\'' +
", goodsPrice='" + goodsPrice + '\'' +
", goodsQuantity='" + goodsQuantity + '\'' +
'}';
}
//无参
public Goods() {
}
//有参
public Goods(int goodsID, String goodsName, String goodsPrice, String goodsQuantity) {
this.goodsID = goodsID;
this.goodsName = goodsName;
this.goodsPrice = goodsPrice;
this.goodsQuantity = goodsQuantity;
}
//get/set方法
public int getGoodsID() {
return goodsID;
}
public void setGoodsID(int goodsID) {
this.goodsID = goodsID;
}
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public String getGoodsPrice() {
return goodsPrice;
}
public void setGoodsPrice(String goodsPrice) {
this.goodsPrice = goodsPrice;
}
public String getGoodsQuantity() {
return goodsQuantity;
}
public void setGoodsQuantity(String goodsQuantity) {
this.goodsQuantity = goodsQuantity;
}
}使用lombok插件!
package com.luo.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Goods {
//实体类
private int goodsID;
private String goodsName;
private String goodsPrice;
private String goodsQuantity;
}编写Dao层的 Mapper接口:GoodsMapper
package com.luo.dao;
import com.luo.pojo.Goods;
import java.util.List;
//Dao层接口
public interface GoodsMapper {
List<Goods> getGoodsList();
//增
int addGoods(Goods goods);
//删
int deleteGoods(int id);
//改
int updateGoods(Goods goods);
//查id
Goods queryGoodsById(int id);
//查全部
List<Goods> queryAllGoods();
}编写接口对应的 Mapper.xml 文件。需要导入MyBatis的包
接口名与映射文件名最好一致
<?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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.luo.dao.GoodsDao">
<!--增-->
<insert id="addGoods" parameterType="com.luo.pojo.Goods">
insert into ssmexercise.goods (id,name,price,quantity)
values (#{id},#{name},#{price},#{quantity});
</insert>
<!--删-->
<delete id="deleteGoods" parameterType="com.luo.pojo.Goods">
delete from ssmexercise.goods where id=(#{id});
</delete>
<!-- 改-->
<update id="updateGoods" parameterType="com.luo.pojo.Goods">
update ssmexercise.goods set name=#{name},price=#{price},
quantity=#{quantity} where id=#{id};
</update>
<!-- id查询-->
<select id="queryGoodsById" parameterType="com.luo.pojo.Goods">
select * from ssmexercise.goods where id=#{id}
</select>
<!-- 全部查询-->
<select id="queryAllGoods" resultType="com.luo.pojo.Goods">
select * from ssmexercise.goods
</select>
</mapper>编写Service(服务)层的接口和实现类
接口:GoodsService
package com.luo.service;
import com.luo.pojo.Goods;
import java.util.List;
public interface GoodsService {
List<Goods> getGoodsList();
//增
int addGoods(Goods goods);
//删
int deleteGoods(int id);
//改
int updateGoods(Goods goods);
//查id
Goods queryGoodsById(int id);
//查全部
List<Goods> queryAllGoods();
}实现类 :GoodsServiceImpl
package com.luo.service;
import com.luo.dao.GoodsMapper;
import com.luo.pojo.Goods;
import java.util.List;
public class GoodsServiceImpl implements GoodsService{
//service调dao层:组合Dao
private GoodsMapper goodsMapper;
public void setGoodsMapper(GoodsMapper goodsMapper) {
this.goodsMapper = goodsMapper;
}
public List<Goods> getGoodsList() {
return goodsMapper.getGoodsList();
}
public int addGoods(Goods goods) {
return goodsMapper.addGoods(goods);
}
public int deleteGoods(int id) {
return goodsMapper.deleteGoods(id);
}
public int updateGoods(Goods goods) {
return goodsMapper.updateGoods(goods);
}
public Goods queryGoodsById(int id) {
return goodsMapper.queryGoodsById(id);
}
public List<Goods> queryAllGoods() {
return goodsMapper.queryAllGoods();
}
}到此,底层需求操作编写完毕
Spring层
配置Spring整合MyBatis,我们这里数据源使用c3p0连接池
我们去编写Spring整合Mybatis的相关的配置文件;spring-dao.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.关联数据库配置文件-->
<context:property-placeholder location="classpath:database.properties"/>
<!-- 2.连接池
dbcp:半自动化操作,不能自动连接
c3p0:自动化操作(自动化的加载配置文件,并且可以自动设置到对象中!)
druid:hikari
-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- c3p0连接池的私有属性 -->
<property name="maxPoolSize" value="30"/>
<property name="minPoolSize" value="10"/>
<!-- 关闭连接后不自动commit -->
<property name="autoCommitOnClose" value="false"/>
<!-- 获取连接超时时间 -->
<property name="checkoutTimeout" value="10000"/>
<!-- 当获取连接失败重试次数 -->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!-- 3.sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 绑定Mybatis的配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!-- 4.配置dao接口扫描包,动态的实现了Dao接口可以注入到Spring容器中-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 要扫描的dao包-->
<property name="basePackage" value="com.luo.dao"/>
</bean>
</beans>Spring整合service层
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.扫描service下的包-->
<context:component-scan base-package="com.luo.service"/>
<!-- 2.将我们的所有业务类,注入到Spring,可以通过配置,或者注解实现-->
<bean id="GoodsServiceImpl" class="com.luo.service.GoodsServiceImpl">
<property name="goodsMapper" ref="goodsMapper"/>
</bean>
<!-- 3.声明式事务配置-->
<bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 4.aop事务支持-->
</beans>SpringMVC层
添加web支持
右击项目文件,选择添加框架支持

勾选Web应用程序,点击确认

web添加成功

如果新建项目时选择了从原型创建 则可省略此步

配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- DispatchServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 乱码过滤-->
<filter>
<filter-name>encodingFilter</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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Session-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.注解驱动-->
<mvc:annotation-driven/>
<!-- 2.静态资源过滤-->
<mvc:default-servlet-handler/>
<!-- 3.扫描包:controller-->
<context:component-scan base-package="com.luo.controller"/>
<!-- 4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>配置文件,暂时结束!Controller 和 视图层编写
GoodsController 类编写 , 方法一:查询全部书籍
package com.luo.controller;
import com.luo.pojo.Goods;
import com.luo.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/Goods")
public class GoodsController {
//controller调service层
@Autowired
@Qualifier("GoodsServiceImpl")
private GoodsService goodsService;
//查询全部的书籍,并且返回到一个书籍展示页面
@RequestMapping("/allGoods")
public String list(Model model){
List<Goods> list = goodsService.queryAllGoods();
model.addAttribute("list",list);
return "allGoods";
}
}编写首页 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<h3>
<a href="${pageContext.request.contextPath}/Goods/allGoods">进入货物页面</a>
</h3>
</body>
</html>配置tomcat
点击右上角添加配置,点击 + 号添加新配置

选中tomcat服务器本地

点击修正,部署工件

点击应用并确定,部署完毕

运行一下,报错

原因:
IDEA maven导入springMVC出现错误
解决方法:
这种情况下,我们就需要将maven的包手动导入,才能将项目跑起来。步骤如下
打开项目结构

点击构件,然后点击WEB-INF目录,点击新建文件夹按钮,创建lib文件夹

然后引入库

全选即可,点击确定,需要的jar包便全部导入到项目中

项目即可成功启动


货物列表页面 allGoods.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>货物展示</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>货物列表 —— 显示所有货物</small>
</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 column">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/Goods/toAddGoods">新增</a>
</div>
</div>
<div class="row clearfix">
<div class="col-md-12 column">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>货物编号</th>
<th>货物名称</th>
<th>货物单价</th>
<th>货物数量</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="goods" items="${requestScope.get('list')}">
<tr>
<td>${goods.goodsID}</td>
<td>${goods.goodsName}</td>
<td>${goods.goodsPrice}</td>
<td>${goods.goodsQuantity}</td>
<td>
<a href="${pageContext.request.contextPath}/Goods/toUpdateGoods?id=${goods.goodsID}">更改</a> |
<a href="${pageContext.request.contextPath}/Goods/del/${goods.goodsID}">删除</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>重启服务器,点击进入货物页面,发现报500错误

问题:bean不存在
步骤:
1.查看这个bean注入是否成功 ok
2.Junit单元测试,看我们的代码是否能够查询出来结果 ok
3.问题,一定不在我们的底层,是spring出了问题
4.SpringMVC,整合的时候没调用到我们的service层的bean
1.applicationContext.xml 没有注入bean
2.web.xml中,我们也绑定过配置文件,发现问题,我们配置的是Spring-mvc.xml,这里面确实没有service bean,所以报空指针
刷新一下,成功但发现新的问题


SSM框架,test测试插入数据,操作成功,但数据库没有数据
问题原因
检查数据库字段名
我的数据库的字段:id,name,price,quantity
javaBean的实体类属性名:

由于查询结果的字段为id,name,price,quantity,在实体类中没有定义,所以查询结果为null
解决方案一
修改实体类为:goodsID,goodsName,goodsPrice,goodsQuantity,问题得到解决 能正常的查询到数据,
同样需要set get。
解决方案二
修改数据库字段名

方案总结
如果使用select * 来查询的 那么实体类中的属性必须和数据表中对应的字段一模一样
GoodsController 类编写 , 方法二:添加货物
@RequestMapping("/toAddGoods")
public String toAddPaper() {
return "addGoods";
}
@RequestMapping("/addGoods")
public String addPaper(Goods goods) {
System.out.println(goods);
goodsService.addGoods(goods);
return "redirect:/Goods/allGoods";
}添加货物页面:addGoods.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>新增货物</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 引入 Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="page-header">
<h1>
<small>新增货物</small>
</h1>
</div>
</div>
</div>
<form action="${pageContext.request.contextPath}/Goods/addGoods" method="post">
货物名称:<input type="text" name="goodsName"><br><br><br>
货物单价:<input type="text" name="goodsPrice"><br><br><br>
货物数量:<input type="text" name="goodsQuantity"><br><br><br>
<input type="submit" value="添加">
</form>
</div>
</body>
</html>测试一下,报错

错误原因:
id是goods表的主键id,错误提示此id没有默认值,去数据库设计表看了下表结构,我在新建表字段的时候,没有将id设置为自增长类型(主键自增)。
解决办法:
将主键id设置为“自动递增”,并删除冲突的数据
















