SSM框架基础知识-Spring-Spring整合MyBatis
一、结构
二、数据库准备
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,`job` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`salary` double NULL DEFAULT NULL,`hire_date` date NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
三、引入 Maven 依赖
首先在 pom.xml
中配置所有依赖,核心是 Spring 上下文、MyBatis 核心包、整合包、数据库驱动和连接池:
<dependencies><!-- 1. Spring 核心依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId> <!-- Spring 对 JDBC 的支持 --><version>5.2.5.RELEASE</version></dependency><!-- 2. MyBatis 核心依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.1</version></dependency><!-- 3. MyBatis 与 Spring 整合依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.1</version></dependency><!-- 4. MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version> <!-- 适配 MySQL 5.x;若用8.x,需换8.0+版本 --></dependency><!-- 5. Druid 连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency>
</dependencies>
四、编写核心组件
1. 实体类(Emp.java)
对应数据库 emp
表:
package com.example.entity;import java.util.Date;/*** 员工实体类*/
public class Emp {private Integer id;private String name;private String job;private Double salary;private Date hireDate;public Emp() {}public Emp(Integer id ,String name, String job, Double salary, Date hireDate) {this.id = id;this.name = name;this.job = job;this.salary = salary;this.hireDate = hireDate;}// getter和setterpublic Integer getId() { return id; }public void setId(Integer id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getJob() { return job; }public void setJob(String job) { this.job = job; }public Double getSalary() { return salary; }public void setSalary(Double salary) { this.salary = salary; }public Date getHireDate() { return hireDate; }public void setHireDate(Date hireDate) { this.hireDate = hireDate; }@Overridepublic String toString() {return "Emp{" +"id=" + id +", name='" + name + '\'' +", job='" + job + '\'' +", salary=" + salary +", hireDate=" + hireDate +'}';}
}
2. Mapper 接口(EmpMapper.java)
MyBatis 映射接口,定义数据访问方法(无需实现类,MyBatis 会动态生成代理):
package com.example.mapper;import com.example.entity.Emp;
import org.apache.ibatis.annotations.Param;import java.util.List;
import java.util.Map;/*** 员工数据访问类*/
public interface EmpMapper {List<Emp> getAllEmps();
}
3. MyBatis 映射文件(EmpMapper.xml)
与 EmpMapper
接口绑定,编写 SQL 语句,放在 resources/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="com.example.mapper.EmpMapper"><!--查询所有员工--><select id="getAllEmps" resultType="Emp" >SELECT id, name, job, salary, hire_date as hireDate FROM emp</select>
</mapper>
- 关键说明:
namespace
:绑定EmpMapper
接口,确保 MyBatis 能找到对应方法。resultType="Emp"
:指定返回结果类型为Emp
实体(需在 Spring 中配置别名扫描,否则需写全路径com.example.entity.Emp
)。- 字段映射:数据库字段
hire_date
用as hireDate
转换为实体类属性名,避免字段不匹配。
4. 数据库配置(db.properties)
存储数据库连接信息,解耦配置(便于维护):
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/jdbc_test?useSSL=false&serverTimezone=UTC&characterEncoding=utf-8&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=123456
5. Spring 核心配置(applicationContext.xml)
这是整合的核心,配置 Spring 容器、数据源、SqlSessionFactory、Mapper 扫描等,放在 resources
目录下:
<?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"><!--注解扫描--><context:component-scan base-package="com.example"/><!--加载配置文件--><context:property-placeholder location="classpath:db.properties"/><bean id="configuration" class="org.apache.ibatis.session.Configuration"><property name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/></bean><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!--创建sqlSessionFactory--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/><property name="mapperLocations" value="classpath:mapper/*.xml"/><property name="typeAliasesPackage" value="com.example.entity"/><property name="configuration" ref="configuration"/><!--可用于加载mybatis配置文件。<property name="configLocation" value="classpath:mybatis.xml"/>--></bean><!--创建mapper代理类。默认以接口名首字母小写作为Bean名称。SqlSessionTemplate.getMapper()--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><!--以下代码可以不写,注意这里是value--><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><property name="basePackage" value="com.example.mapper"/></bean></beans>
- 核心配置解析:
SqlSessionFactoryBean
:替代 MyBatis 原生的SqlSessionFactory
,整合 Spring 数据源,自动加载映射文件。MapperScannerConfigurer
:扫描com.example.mapper
包下的接口,为每个接口生成代理对象,并注册到 Spring 容器,Bean 名称默认是「接口名首字母小写」(如EmpMapper
→empMapper
)。sqlSessionFactoryBeanName
:用value
而非ref
,因为MapperScannerConfigurer
是BeanDefinitionRegistryPostProcessor
,初始化时机早于sqlSessionFactory
实例化,只能通过名称延迟查找。
五、编写测试类验证
通过 Spring 容器获取 EmpMapper
代理对象,调用 getAllEmps()
方法查询所有员工:
package com.example;import com.example.entity.Emp;
import com.example.mapper.EmpMapper;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;/*** Spring + MyBatis 整合测试类*/
public class Test {public static void main(String[] args) {// 1. 加载Spring配置文件,初始化容器ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");// 2. 从容器中获取EmpMapper代理对象(Bean名称:empMapper)EmpMapper empMapper = applicationContext.getBean("empMapper", EmpMapper.class);// 3. 调用方法查询所有员工List<Emp> empList = empMapper.getAllEmps();// 4. 打印结果System.out.println("=== 所有员工信息 ===");for (Emp emp : empList) {System.out.println(emp);}// 5. 关闭容器applicationContext.close();}
}
六、运行结果与常见问题
1. 预期运行结果
=== 所有员工信息 ===
Emp{id=1, name='张三', job='Java开发', salary=15000.0, hireDate=2023-01-10}
Emp{id=2, name='李四', job='产品经理', salary=18000.0, hireDate=2022-09-15}
Emp{id=3, name='王五', job='测试工程师', salary=12000.0, hireDate=2023-03-20}
2. 常见问题与解决方案
问题描述 | 原因 | 解决方案 |
---|---|---|
找不到 EmpMapper Bean | Mapper 扫描包配置错误 | 检查 MapperScannerConfigurer 的 basePackage 是否为 com.example.mapper |
字段不匹配(hireDate 为 null) | 数据库字段 hire_date 与实体类 hireDate 未映射 | SQL 中加 as hireDate ,或用 MyBatis 结果映射 <resultMap> |
数据库连接失败 | 驱动类、URL、账号密码错误 | 1. 检查 db.properties 配置;2. MySQL 服务是否启动;3. 8.x 驱动需换 com.mysql.cj.jdbc.Driver |
SqlSessionFactory 找不到 | sqlSessionFactoryBeanName 用了 ref | 改为 value="sqlSessionFactory" ,因为 MapperScannerConfigurer 初始化早 |