一、SpringBoot之SSM技术整合
1、SpringBoot ssm环境搭建
(1)创建项目
右键SpringBoot->新建->新模块


下一步:
集成ssm环境,搭建环境,集成MyBatis,数据库

点击完成即可

(2)resources下的application.properties删掉换成application.yml文件
application.yml中:
设置服务器端口,
启动一下:

2、MBG逆向工程
(1)首先连接数据库



(2)逆向生成
①、在pom.xml中增加:
<!--逆向工程依赖-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency><!--插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<configuration>
<configurationFile>
<!--这里是配置generatorConfig.xml的路径 不写默认在resources目录下找generatorConfig.xml文件-->
</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
②、导入配置文件(放在resources下):
Generator.properties:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/SpringBoot?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true jdbc.username=root jdbc.password=123456 jdbc.driverLocation=E:\\Maven\\init\\mysql\\mysql-connector-java\\8.0.22\\mysql-connector-java-8.0.22.jar model.package=com.mwy.code.pojo mapper.package=com.mwy.code.dao xml.mapper.package=mapper
generatorConfig.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<properties resource="generator.properties"/>
<!--指定数据库jdbc驱动jar包的位置-->
<classPathEntry location="${jdbc.driverLocation}"/>
<context id="MySqlContext" targetRuntime="MyBatis3" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<property name="javaFileEncoding" value="UTF-8"/>
<!--生成mapper.xml时覆盖原文件-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<plugin type="org.mybatis.generator.plugins.MyBatisPlugin">
<property name="hasLombok" value="true"/>
</plugin>
<!--可以自定义生成model的代码注释-->
<commentGenerator>
<property name="suppressAllComments" value="true"/> <!-- 是否取消注释 -->
<property name="suppressDate" value="true"/> <!-- 是否生成注释代时间戳 -->
</commentGenerator>
<!--配置数据库连接-->
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}"
password="${jdbc.password}">
<!--解决mysql驱动升级到8.0后不生成指定数据库代码的问题-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制-->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--指定pojo生成位置-->
<javaModelGenerator targetPackage="${model.package}" targetProject="src\main\java"/>
<!--指定生成mapper.xml的路径-->
<sqlMapGenerator targetPackage="${xml.mapper.package}" targetProject="src\main\resources"/>
<!--指定生成mapper接口的的路径-->
<javaClientGenerator type="XMLMAPPER"
targetPackage="${mapper.package}"
targetProject="src\main\java"/>
<table tableName="student" domainObjectName="Student">
<!--<columnOverride column="create_time" javaType="java.sql.Timestamp" jdbcType="timestamp"/>-->
<!--<columnOverride column="modify_time" javaType="java.sql.Timestamp" jdbcType="timestamp"/>-->
<property name="enableCountByExample" value="false"/>
<property name="enableDeleteByExample" value="false"/>
<property name="enableDeleteByPrimaryKey" value="false"/>
<property name="enableInsert" value="false"/>
<property name="enableSelectByPrimaryKey" value="false"/>
<property name="enableUpdateByExample" value="false"/>
<property name="enableUpdateByPrimaryKey" value="false"/>
<property name="selectByExampleQueryId" value="true"/>
<property name="selectByPrimaryKeyQueryId" value="false"/>
<!--自动生成主键,可以代替useGeneratedKeys-->
<generatedKey column="stu_id" sqlStatement="Mysql" type="post" identity="true"/>
</table>
</context>
</generatorConfiguration>
⑤、generatorConfig.xml还是有点问题,因此导入MyBatisPlugin类(自动生成注释,注解,属性),java下新建org.mybatis.generator.plugins软件包,MyBatisPlugin类放在org.mybatis.generator.plugins软件包下;
MyBatisPlugin是一个MyBatis插件
package org.mybatis.generator.plugins;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
public class MyBatisPlugin extends PluginAdapter {
@Override
public boolean validate(List<String> list) {
return true;
}
// 生成在类上面的注解
@Override
public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
boolean hasLombok = Boolean.parseBoolean(getProperties().getProperty("hasLombok", "false"));
log.warn("hasLombok:\t" + hasLombok);
if (hasLombok) {
topLevelClass.addImportedType("lombok.Data");
topLevelClass.addImportedType("lombok.NoArgsConstructor");
topLevelClass.addImportedType("lombok.AllArgsConstructor");
topLevelClass.addImportedType("lombok.experimental.Accessors");
topLevelClass.addAnnotation("@Data");
topLevelClass.addAnnotation("@NoArgsConstructor");
topLevelClass.addAnnotation("@AllArgsConstructor");
topLevelClass.addAnnotation("@Accessors(chain = true)");
}
topLevelClass.addJavaDocLine("/**");
String remarks = introspectedTable.getRemarks();
log.error("@table\t" + remarks);
StringBuilder sb = new StringBuilder();
topLevelClass.addJavaDocLine(" * "+remarks + "\t" + introspectedTable.getFullyQualifiedTable());
topLevelClass.addJavaDocLine(" * @author mwy");
topLevelClass.addJavaDocLine(" * @date " + LocalDateTime.now());
topLevelClass.addJavaDocLine(" */");
return true;
}
@Override
public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) {
field.addJavaDocLine("/**");
String remarks = introspectedColumn.getRemarks();
log.error("@column\t" + remarks);
field.addJavaDocLine(" * " + remarks);
field.addJavaDocLine(" */");
return true;
}
// 生成接口
@Override
public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
interfaze.addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
interfaze.addAnnotation("@Mapper");
interfaze.addImportedType(new FullyQualifiedJavaType("org.springframework.stereotype.Repository"));
interfaze.addAnnotation("@Repository");
interfaze.addJavaDocLine("/**");
interfaze.addJavaDocLine(" * @author mwy");
interfaze.addJavaDocLine(" * @date " + LocalDateTime.now());
interfaze.addJavaDocLine(" */");
return true;
}
@Override
public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) {
boolean hasLombok = Boolean.parseBoolean(getProperties().getProperty("hasLombok", "false"));
return !hasLombok;
}
@Override
public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, Plugin.ModelClassType modelClassType) {
boolean hasLombok = Boolean.parseBoolean(getProperties().getProperty("hasLombok", "false"));
return !hasLombok;
}
}取org.mybatis.generator.plugins这个名字是因为等下这个类要放到jar包里面去,点击上面的小锤头编译MyBatisPlugin类,
拿到编译的类, 并复制

是一个class文件

找到逆向生成工程本地仓库

找到后右键压缩文件预览
将MyBatisPlugin.class文件增加进去

④、 开始生成:双击即可

pojo和dao自动生成了

⑤、给myBatis配置
application.yml:配置数据源
Spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/SpringBoot?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true测试是否获取到数据源,获取成功
查看是否能获得连接:

application.yml:配置myBatis
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.mwy.code.pojo
configuration:
map-underscore-to-camel-case: trueapplication.yml:
server:
port: 8080
Spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/SpringBoot?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.mwy.code.pojo
configuration:
map-underscore-to-camel-case: true测试是否注入成功:

application.yml: 增加日志打印
server:
port: 8080
Spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/SpringBoot?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.mwy.code.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.mwy.code.dao: debug增加日志打印后会出现sql语句打印:

3、ssm开发
(1)写service层
①、新建接口StudentService
package com.mwy.code.service;
import com.mwy.code.pojo.Student;
import java.util.List;
public interface StudentService {
List<Student> select();
Student selectOne(Student student);
int add(Student student);
int del(Student student);
int upd(Student student);
}
②、实现接口StudentServiceImpl
package com.mwy.code.service;
import com.mwy.code.dao.StudentMapper;
import com.mwy.code.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper mapper;
@Override
@Transactional(rollbackFor = Exception.class)
public List<Student> select() {
return mapper.select();
}
@Override
public Student selectOne(Student student) {
return mapper.selectOne(student);
}
@Override
public int add(Student student) {
return mapper.add(student);
}
@Override
public int del(Student student) {
return mapper.del(student);
}
@Override
public int upd(Student student) {
return mapper.upd(student);
}
}
(2)写controller层
StudentController :
package com.mwy.code.controller;
import com.mwy.code.pojo.Student;
import com.mwy.code.service.StudentService;
import com.mwy.code.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("stu")
public class StudentController {
StudentService studentService;
@Autowired
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
@GetMapping
public Object select(HttpServletRequest request){
PageBean pageBean=new PageBean();
pageBean.setRequest(request);
return studentService.selectPager(pageBean);
}
@GetMapping("/{stuId}")
public Object selectOne(@PathVariable Long stuId){
return studentService.selectOne(new Student().setStuId(stuId));
}
@DeleteMapping("/{stuId}")
public Object del(@PathVariable Long stuId){
return studentService.del(new Student().setStuId(stuId));
}
@PostMapping
public Object add(Student student){
return studentService.add(student);
}
@PutMapping
public Object upd(Student student){
return studentService.upd(student);
}
}有一个在浏览器中不能用,以下是解决方法:
装插件:postman
使用:axios(开启跨域)
(3)测试程序能否启动

点击查询的小火箭,得到结果:
查询所有:

查询单个:

4、集成PageHelper
(1)导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>(2)启动类打开自动代理

(3)分页
①、新建util包,里面放入pageBean
package com.mwy.code.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private int total;
private int page = 1;
private int rows = 5;
private boolean pagination = true;
private String url;
private Map<String, String[]> ms;
public void setMs(Map<String, String[]> ms) {
this.ms = ms;
}
public int calcStartIndex() {
return (page - 1) * rows;
}
public int calcMaxPage() {
return total % rows == 0 ? total / rows : total / rows + 1;
}
public int nextPage() {
return Math.min(page + 1, calcMaxPage());
}
public int prevPage() {
return Math.max(page - 1, 1);
}
public void setRequest(HttpServletRequest req) {
setUrl(req.getRequestURL().toString());
setMs(req.getParameterMap());
String page = req.getParameter("page");
if (page == null) {
setPage(1);
} else {
setPage(Integer.parseInt(page));
}
String rows = req.getParameter("rows");
if (rows == null) {
setRows(5);
} else {
setRows(Integer.parseInt(rows));
}
String pagination = req.getParameter("pagination");
if ("false".equals(pagination)) {
setPagination(false);
}
}
}②、切面包,里面放入PageAspect
package com.mwy.code.aspect;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mwy.code.util.PageBean;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Slf4j
public class PageAspect {
@Around(value = "execution(* *..*Service.*Pager(..))")
public Object invoke(ProceedingJoinPoint point) throws Throwable {
PageBean pageBean = null;
for (Object e : point.getArgs()) {
if (e instanceof PageBean) {
pageBean = (PageBean) e;
break;
}
}
if (pageBean != null && pageBean.isPagination()) {
PageHelper.startPage(pageBean.getPage(), pageBean.getRows());
}
Object obj = point.proceed(point.getArgs());
if (obj != null) {
if (obj instanceof Page) {
Page page = (Page) obj;
PageInfo pageInfo = new PageInfo(page);
pageBean.setTotal(new Long(pageInfo.getTotal()).intValue());
return pageInfo.getList();
}
}
return obj;
}
}③、修改StudentService
List<Student> selectPager(PageBean pageBean);
④、修改StudentServiceImpl
@Override
@Transactional(rollbackFor = Exception.class)
public List<Student> selectPager(PageBean pageBean) {
return mapper.select();
}⑤、修改StudentController
@GetMapping
public Object select(HttpServletRequest request){
PageBean pageBean=new PageBean();
pageBean.setRequest(request);
return studentService.selectPager(pageBean);
}⑥、测试
启动程序:

测试分页:

5、集成通用Mapper
增删改查方法全部不用写,直接调
(1)导入pom依赖
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>(2)修改mapper
删除StudentMapper中的注解@mapper

修改启动类的MapperScan (注意导包 tk.mybatis.spring.annotation.MapperScan )

这样他就会自动扫描StudentMapper,不需要写mapper映射
(3)表注解(pojo类)
①、解决实体类属性名不一致的问题,
@Table(name="tb_brand") 指定要映射的数据库中的哪个表@Id 表示该成员变量是主键 id@GeneratedValue(strategy = GenerationType.IDENTITY) 标识该主键的策略 , 自增@Column(name = "name") 标识该成员变量跟数据库中的 name 字段映射@Transient 不是表字段
基础接口
②、pom.xml
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
③、Student .java

④、注掉StudentMapper.java中方法,继承Mapper与Student挂钩

⑤、注掉StudentMapper.xml中方法

StudentService不用改;
修改StudentServiceImpl :
package com.mwy.code.service;
import com.mwy.code.dao.StudentMapper;
import com.mwy.code.pojo.Student;
import com.mwy.code.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper mapper;
@Override
@Transactional(rollbackFor = Exception.class)
public List<Student> selectPager(PageBean pageBean) {
return mapper.selectAll();
}
@Override
public Student selectOne(Student student) {
return mapper.selectOne(student);
}
@Override
public int add(Student student) {
return mapper.insert(student);
}
@Override
public int del(Student student) {
return mapper.deleteByPrimaryKey(student);
}
@Override
public int upd(Student student) {
return mapper.updateByPrimaryKey(student);
}
}⑥、增删改查方法全部不用写,直接调(SpringBoot03ApplicationTests.java)

查询所有:

它提供了所有的方法;
基础接口
setDistinct(boolean distinct) 查询的结果是否要进行唯一性过滤, true 表示过滤, false (默认)表示不过滤。 Criteriavoid setOrderByClause(String orderByClause) 查询结果按照某个,或者某些字段进行升序,降序,比如参数是 “id asc” 就是按照 id 进行升序, “id asc , age desc” 就是按照 id 升序,在 id 相等 的情况下,按照 age 降序。Example selectProperties(String... properties) 当利用 example 进行查询时,此方法可以设置想要查询的字段是哪些Example.OrderBy orderBy(String property) 排序,与 setOrderByClause 功能一样,只是用法不同比如 orderBy("id").asc() 表示按照 id 升序,orderBy("id").asc().orderBy("age").desc() 表示按照 id 升序,再按照 age 降序Example.Criteria or() 创建一个 or 方式的、空的 criteriavoid or(Example.Criteria criteria) 直接以 or 的方式添加一个现有的 criteriaExample.Criteria and() 同上,不过是 and 方式void and(Example.Criteria criteria) 同上, and 方式
criteria.andIsNull( 字段名 );添加字段 xx 为 null 的条件criteria.andIsNotNull( 字段名 );添加字段 xx 不为 null 的条件criteria.andEqualTo( 字段名 ,value);添加 xx 字段等于 value 条件criteria.andNotEqualTo( 字段名 ,value);添加 xx 字段不等于 value 条件criteria.andGreaterThan( 字段名 ,value);添加 xx 字段大于 value 条件criteria.andGreaterThanOrEqualTo( 字段名 ,value);添加 xx 字段大于等于 value 条件criteria.andLessThan( 字段名 ,value);添加 xx 字段小于 value 条件criteria.andLessThanOrEqualTo( 字段名 ,value);添加 xx 字段小于等于 value 条件criteria.andIn( 字段名 ,list);添加 xx 字段值在 List 条件criteria.andNotIn( 字段名 ,list);添加 xx 字段值不在 List 条件criteria.andLike( 字段名 ,“%”+value+”%”);添加 xx 字段值为 value 的模糊查询条件criteria.andNotLike( 字段名 ,“%”+value+”%”);添加 xx 字段值不为 value 的模糊查询条件criteria.andBetween( 字段名 ,value1,value2);添加 xx 字段值在 value1 和 value2 之间条件criteria.andNotBetween( 字段名 ,value1,value2);添加 xx 字段值不在 value1 和 value2 之间条件
andEqualTo 相当于等于
andLike:模糊查询

结果:
没有打印,但是查询出来了,有六条数据

Test下: SpringBoot03ApplicationTests 类
package com.mwy.code;
import com.mwy.code.dao.StudentMapper;
import com.mwy.code.pojo.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import tk.mybatis.mapper.entity.Example;
import javax.sql.DataSource;
@SpringBootTest
class SpringBoot03ApplicationTests {
@Autowired
DataSource dataSource;
@Autowired
StudentMapper studentMapper;
@Test
void contextLoads() throws Exception{
System.out.println(dataSource);
System.out.println(dataSource.getConnection());
// System.out.println(studentMapper.select());
System.out.println(studentMapper.selectAll());
Example example=new Example(Student.class);
Example.Criteria c1=example.createCriteria();
//c1.andLike("stuName","concat('%',马,'%')");
c1.andLike("stuName", "%马%");
// 想用sql语句查询,它会直接拼接sql
//c1.andCondition("stu_class=3");
studentMapper.selectByExample(example);
}
}结束
