今天的学习内容分为两大块:上午的Maven项目管理工具和下午的MyBatis持久层框架。如果说之前手写JDBC是"手工打造",那么今天学习的Maven和MyBatis就是"工业化的流水线"------前者解决依赖管理和项目构建,后者简化数据库操作。两者结合,让Java后端开发真正进入了框架时代。
一、Maven------项目管理的基石
为什么需要Maven?
在Maven出现之前,Java项目的依赖管理是一场噩梦:需要手动下载jar包、处理版本冲突、配置类路径。Maven的出现彻底改变了这一切。
Maven的三大作用:
-
依赖管理:自动下载jar包及其传递依赖
-
一键构建:编译、测试、打包、部署一条龙
-
聚合工程:支持多模块项目管理
仓库体系
Maven的仓库分为三层:
| 仓库类型 | 说明 | 优先级 |
|----------|------|--------|
| 本地仓库 | 本地硬盘上的jar存放位置 | 最高 |
| 远程仓库 | 局域网/私服仓库 | 中 |
| 中央仓库 | 全球共享的核心仓库 | 最低 |
查找顺序:本地仓库 → 远程仓库 → 中央仓库。本地仓库配置:
```xml
<localRepository>D:\develop\repository</localRepository>
```
POM文件------项目的身份证
POM(Project Object Model)是Maven项目的核心配置文件,最关键的三个坐标:
```xml
<groupId>cn.javasm</groupId> <!-- 组织/公司 -->
<artifactId>maven01</artifactId> <!-- 项目名 -->
<version>1.0-SNAPSHOT</version> <!-- 版本号 -->
```
版本号的含义:
-
`SNAPSHOT`:快照版,开发阶段,远程仓库不让传
-
`alpha`:内测版
-
`beta`:进一步内测版
-
`GA`:生产版本
打包方式:
-
`jar`:默认,普通Java项目
-
`war`:Web项目
-
`pom`:聚合工程(父工程)
项目生命周期
Maven的生命周期是标准化的,常用的命令按顺序为:
| 命令 | 作用 |
|------|------|
| `clean` | 清理target目录 |
| `compile` | 编译源代码为class文件 |
| `test` | 执行所有测试方法 |
| `package` | 打包到target |
| `install` | 安装到本地仓库 |
| `deploy` | 部署到远程仓库 |
依赖作用域------最容易被忽视的知识点
| scope | 编译 | 测试 | 运行 | 打包 | 典型场景 |
|-------|------|------|------|------|----------|
| compile| ✅ | ✅ | ✅ | ✅ | 最常用,如mybatis |
| provided | ✅ | ✅ | ❌ | ❌ | servlet-api(tomcat已包含) |
| runtime | ❌ | ✅ | ✅ | ✅ | mysql驱动(编译只需接口) |
| test | ❌ | ✅ | ❌ | ❌ | junit |
关键理解:
-
`provided`:servlet包在Tomcat中已有,如果打包会造成版本冲突
-
`runtime`:mysql驱动是接口的实现类,编译时只需接口声明,运行时才需要实现
-
`test`:junit只在测试阶段使用
阿里云镜像配置
为了加速jar包下载,配置国内镜像:
```xml
<mirror>
<id>aliyunmaven</id>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public\</url>
<mirrorOf>central</mirrorOf>
</mirror>
二、MyBatis------持久层框架的优雅
什么是MyBatis?
MyBatis是一个持久层框架,它的前身是Apache的iBatis,2010年迁移到Google后改名MyBatis,2013年迁移到GitHub。
MyBatis的核心价值:免除几乎所有的JDBC代码以及设置参数和获取结果集的工作。通过XML或注解配置SQL语句和映射关系,让开发更聚焦于业务。
MyBatis的优点:
-
减少代码量(不用写繁琐的JDBC代码)
-
基于SQL语法,简单易学
-
SQL语句封装在配置文件中,便于统一管理
-
程序调试方便
快速入门------准备工作
- 导入依赖:
```xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.19</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
- 主配置文件(mybatis-config.xml):
```xml
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
基本CRUD
查询:
```xml
<select id="findUserById" parameterType="int" resultType="cn.javasm.entity.User">
SELECT * FROM user WHERE id = #{abc}
</select>
新增(返回主键):
```xml
<insert id="addUser" parameterType="cn.javasm.entity.User">
<selectKey keyProperty="id" order="AFTER" resultType="int">
SELECT LAST_INSERT_ID()
</selectKey>
INSERT INTO user (username, birthday, sex, address)
VALUES (#{username}, #{birthday}, #{sex}, #{address})
</insert>
`<selectKey>`标签的`order="AFTER"`表示在插入后执行,获取最新主键。
#{} 和 ${} 的区别(重点)
| 符号 | 行为 | 安全性 |
|------|------|--------|
| `#{}` | 预编译,字符串自动加引号 | 防SQL注入 |
| `${}` | 直接拼接原值 | 有SQL注入风险 |
```sql
-- #{} 传入 "gfs"
INSERT INTO user VALUES(NULL, 'gfs', 20) -- 字符串带引号
-- ${} 传入 "gfs"
INSERT INTO user VALUES(NULL, gfs, 20) -- 字符串不带引号,会报错
```
使用原则:一般情况下都用`#{}`,只有模糊查询或引用列名时使用`${}`。
Mapper代理开发(重点)
MyBatis最强大的特性之一是Mapper代理开发,只需定义接口,无需实现类!
四条书写规范:
-
Mapper接口的完整路径要与mapper.xml的`namespace`一致
-
接口方法名要与标签的`id`值一致
-
参数处理:
-
单个参数:`#{}`中名字随便写
-
多个参数:用`#{arg0}`、`#{param1}`或加`@Param`注解
-
实体参数:`#{}`中直接写属性名
- 返回值要与`resultType`一致
接口定义:
```java
public interface UserMapper {
List<User> selectAll();
User selectUserById(Integer id);
void saveUser(User user);
List<User> selectUserByUsernameAndSex(
@Param("username") String username,
@Param("sex") String s
);
}
```
XML配置:
```xml
<mapper namespace="cn.javasm.mapper.UserMapper">
<select id="selectAll" resultType="cn.javasm.entity.User">
SELECT * FROM user
</select>
<select id="selectUserByUsernameAndSex" resultType="cn.javasm.entity.User">
SELECT * FROM user
WHERE username LIKE '%${username}%' AND sex = #{sex}
</select>
</mapper>
使用:
```java
SqlSession session = sqlSessionFactory.openSession(true); // true表示自动提交
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> users = mapper.selectUserByUsernameAndSex("杰", "女");
```
Mapper代理的魔力:MyBatis通过**JDK动态代理**自动生成接口的实现类。当调用`session.getMapper(UserMapper.class)`时,MyBatis会返回一个代理对象,将方法调用转发到对应的SQL执行。
三、全局配置文件优化
引入properties文件
db.properties:
```properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=root
```
mybatis-config.xml:
```xml
<properties resource="db.properties"/>
...
<property name="driver" value="${jdbc.driverClassName}"/>
```
多环境配置
```xml
<environments default="development">
<environment id="development">...</environment>
<environment id="test">...</environment>
<environment id="www">...</environment>
</environments>
```
通过`default`属性切换环境,方便在开发、测试、生产环境间切换。
开启日志
```xml
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
```
开启后可以在控制台看到MyBatis执行的SQL语句和参数,便于调试。
四、今日总结
今天的学习让我从"手写JDBC"进化到了"使用框架":
| 知识点 | 核心要点 |
|--------|----------|
| Maven作用 | 依赖管理 + 一键构建 + 聚合工程 |
| 仓库体系 | 本地 → 远程 → 中央 |
| POM坐标 | groupId + artifactId + version |
| 生命周期 | clean → compile → test → package → install → deploy |
| 作用域 | compile最常用,provided/runtime/test各有场景 |
| MyBatis | 持久层框架,免除JDBC代码 |
| #{} vs {} \| #{}防注入,{}用于模糊查询和列名 |
| Mapper代理 | 接口+XML,动态代理自动实现 |
| 主键返回 | selectKey标签 + LAST_INSERT_ID() |
三点深刻感悟:
-
Maven是团队协作的基础:统一的项目结构和依赖管理,让不同开发者的代码能无缝集成。阿里云镜像的配置更是提升了国内开发者的效率。
-
MyBatis体现了"约定优于配置":Mapper代理开发中,只要遵循命名规范(namespace=接口全路径,id=方法名),就能自动映射,不需要写一行实现类代码。
-
#{}和${}的区别关乎安全:SQL注入是最常见的安全漏洞之一,理解预编译机制是每个后端开发者的必修课。
明天也继续加油