目录
1、选择spring initializr项目(和上次搭建项目一样步骤)
2、将Generator.properties和generatorConfig.xml文件导入到项目中
3、MyBatisPlugin.class导入org.mybatis.generator.plugins(对应的软件包)下
5、将MyBatisPlugin.class文件赋到本地仓库的org对应版本的压缩下:
一、搭建springBoot项目
1、选择spring initializr项目(和上次搭建项目一样步骤)![](https://img-blog.csdnimg.cn/7170c1a0a30b4be5ae0906246d3be8a5.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASSBXYW50IFRvIElUIE1hc3Rlcg==,size_15,color_FFFFFF,t_70,g_se,x_16)
2、将mybatis相关配置给勾选上
因为整合要用到数据库,所以必须将数据库相关配置给勾选上,如mybatis 工厂以及mybatis驱动类。
3、新项目就搭建完![](https://img-blog.csdnimg.cn/ee9f5b3e057a4fc4915c43753f4102c6.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASSBXYW50IFRvIElUIE1hc3Rlcg==,size_20,color_FFFFFF,t_70,g_se,x_16)
二、MBG(mybatis generator)逆向工程
1、导入相关pom依赖
<!--逆向工程依赖-->
<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>
2、将Generator.properties和generatorConfig.xml文件导入到项目中
注意:两个文件都应放在resource下
Generator.properties文件:
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/stu?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=password
jdbc.driverLocation=D:\\SoftwareInstallPath\\repository\\mysql\\mysql-connector-java\\8.0.27\\mysql-connector-java-8.0.27.jar
model.package=com.yk.code.pojo
mapper.package=com.yk.code.dao
xml.mapper.package=mapper
注意:其中jdbc.driverLocation中的路径为本地maven仓库中的mysql jar包路径,这也是自己将该文件导入进来后要更改的地方
jdbc.driverLocation=D:\\SoftwareInstallPath\\repository\\mysql\\mysql-connector-java\\8.0.27\\mysql-connector-java-8.0.27.jar
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>
3、MyBatisPlugin.class导入org.mybatis.generator.plugins(对应的软件包)下
声明:这是一个生成规范文档注释,生成接口,注解的功能类
为什么将此文件导入到对应的软件包底下:因为到时候要将文件导入到本地仓库中的对应压缩包中去,目的是为了逆向生成代码,
当然还有一种方法就是导入插件,配置mybatis generator生成器
命名行:
mybatis-generator:generate -e
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;
/**
* @author ZJ
*/
@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);
topLevelClass.addJavaDocLine(" * "+remarks + "\t" + introspectedTable.getFullyQualifiedTable());
topLevelClass.addJavaDocLine(" * @author ZJ");
topLevelClass.addJavaDocLine(" * @date " + LocalDateTime.now());
topLevelClass.addJavaDocLine(" */");
return true;
}
@Override
public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, 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 ZJ");
interfaze.addJavaDocLine(" * @date " + LocalDateTime.now());
interfaze.addJavaDocLine(" */");
return true;
}
@Override
public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
boolean hasLombok = Boolean.parseBoolean(getProperties().getProperty("hasLombok", "false"));
return !hasLombok;
}
@Override
public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass, IntrospectedColumn introspectedColumn, IntrospectedTable introspectedTable, ModelClassType modelClassType) {
boolean hasLombok = Boolean.parseBoolean(getProperties().getProperty("hasLombok", "false"));
return !hasLombok;
}
}
项目结构:
4、将项目进行编译
编译成功:
5、将MyBatisPlugin.class文件赋到本地仓库的org对应版本的压缩下:
5.1先查看对应的jar包版本号是多少:
<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>
版本号为1.3.7
5.2找到本地仓库的org包下的1.3.7包
注意看路径:
5.3点击压缩文件预览,将文件赋进去
5.4将文件赋到对应jar中已完成
5.5现在已经可以进行逆向生成代码
双击即可逆向生成代码了:
5.6逆向生成代码完成完毕
修改对应生成路径在 Generator.properties
5.7配置mybaits配置文件
application.yml文件:
server:
port: 8080
spring:
datasource:
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/stu?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
mybatis:
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.yk.code.pojo
configuration:
map-underscore-to-camel-case: true
logging:
level:
com.yk.code.dao: debug
上述有个将显示mybatis日志的代码:
logging: level:
com.yk.code.dao:
debug
整个MBG逆向工程配置完成。
注意:逆向工程完成之后,dao和pojo层就会出现对应的注解,以及文档:那么这个时候mybatis.plugins类就起相应作用了。
三、ssm项目开发
ssm开发和之前的步骤都是一样的
1、首先先写mapper以及mapper.xml层
studentmapper:
package com.yk.code.dao;
import com.yk.code.pojo.Student;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import tk.mybatis.mapper.common.Mapper;
/**
* @author ZJ
* @date 2022-01-20T19:08:42.791
*/
@Repository
public interface StudentMapper extends Mapper<Student> {
List<Student> select();
Student selectOne(Student student);
int add(Student student) ;
int del(Student student) ;
int upd(Student student) ;
}
studentmapper.xml:
<?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">
<mapper namespace="com.yk.code.dao.StudentMapper">
<resultMap id="BaseResultMap" type="com.yk.code.pojo.Student">
<id column="stu_id" jdbcType="BIGINT" property="stuId" />
<result column="stu_name" jdbcType="VARCHAR" property="stuName" />
<result column="stu_phone" jdbcType="VARCHAR" property="stuPhone" />
<result column="stu_class" jdbcType="BIGINT" property="stuClass" />
<result column="stu_address" jdbcType="VARCHAR" property="stuAddress" />
</resultMap>
<insert id="add">
insert into student(stu_name,stu_phone,stu_class,stu_address) values (#{stuName},#{stuPhone},#{stuClass},#{stuAddress})
</insert>
<update id="upd">
update student set stu_name=#{stuName} where stu_id=#{stuId}
</update>
<delete id="del">
delete from student where stu_id=#{stuId}
</delete>
<select id="select" resultType="com.yk.code.pojo.Student">
select * from student
</select>
<select id="selectOne" resultType="com.yk.code.pojo.Student">
select * from student where stu_id=#{stuId}
</select>
</mapper>
2、其次写好service层:
studentservice:
package com.yk.code.service;
import com.yk.code.pojo.Student;
import com.yk.code.util.PageBean;
import java.util.List;
public interface StudentService {
List<Student> selectPager(PageBean pageBean);
Student selectOne(Student student);
int add(Student student) ;
int del(Student student) ;
int upd(Student student) ;
}
studentservice.impl:
package com.yk.code.service.impl;
import com.yk.code.dao.StudentMapper;
import com.yk.code.pojo.Student;
import com.yk.code.service.StudentService;
import com.yk.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 studentMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public List<Student> selectPager(PageBean pageBean) {
return studentMapper.select();
}
@Override
@Transactional(rollbackFor = Exception.class)
public Student selectOne(Student student) {
return studentMapper.selectOne(student);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int add(Student student) {
return studentMapper.add(student);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int del(Student student) {
return studentMapper.del(student);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int upd(Student student) {
return studentMapper.upd(student);
}
}
3、最后写controller层:
studentController:
package com.yk.code.controller;
import com.yk.code.pojo.Student;
import com.yk.code.service.StudentService;
import com.yk.code.util.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpServerErrorException;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/stu")
public class StudentController {
@Autowired
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);
}
}
4、添加事务
@Override
@Transactional(rollbackFor = Exception.class)
public int del(Student student) {
return studentMapper.del(student);
}
但是今天要介绍一种别的说法,今天就用RESTful架构来进行操作,下面是RESTful的官方文档
以下就是上述五种发送请求的格式,
Get:查询
Delete: 删除
Put:增加
Post:更新
Patch:更新
关于RESTful架构上, 写法要特别注意:
正确写法:
@GetMapping("/{stuId}") public Object selectOne(@PathVariable Long stuId){ return studentService.selectOne(new Student().setStuId(stuId)); }
错误写法:
@GetMapping("/:stuId") public Object selectOne(@PathVariable Long stuId){ return studentService.selectOne(new Student().setStuId(stuId)); }
特别要注意:千万不能将{}写成:
四、集成PageHelper
大部分查询数据出来之后都需要分页,所以集成一个PageHelper
1、导入PageHelper依赖
<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、在启动类上开启aop注解
@EnableAspectJAutoProxy
3、导入分页和切面类:
aspect:
package com.yk.code.aspect;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yk.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;
/**
* @author yk
*/
@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;
}
}
PageBean:
package com.yk.code.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @author 银喾
*/
@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);
}
}
}
4、修改对应的方法:
查看以下代码进行对应方法的修改:
@Around(value = "execution(* *..*Service.*Pager(..))") 以上方法是一个环绕通知,其中切面只切service的类,service中以pager结尾的方法所以查询方法要进行更改
service层:
List<Student> selectPager(PageBean pageBean);
controller层:
@GetMapping
public Object select(HttpServletRequest request){
PageBean pageBean=new PageBean();
pageBean.setRequest(request);
return studentService.selectPager(pageBean);
}
分页已经完成:五条数据
五、集成通用Mapper
1、目的:通用mapper目的就是节约时间。
2、步骤:
2.1导入pom依赖:
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
表注解pojo依赖:
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
2.2、修改启动类的MapperScan
@MapperScan("com.yk.code.dao")
注意导包 tk.mybatis.spring.annotation.MapperScan
2.3、在实体类中加上表注明
@Table(name = "student")
@Table(name="tb_brand") 指定要映射的数据库中的哪个表
@Id 表示该成员变量是主键id
@GeneratedValue(strategy = GenerationType.IDENTITY) 标识该主键的策略,自增@Column(name = "name") 标识该成员变量跟数据库中的name字段映射
@Transient 不是表字段
2.4、mapper层继承通用mapper类
public interface StudentMapper extends Mapper<Student> { }
2.5、在测试类进行测试
已查询出结果
这里需要注意的是,关于模糊查询的方法不同:
Example example=new Example(Student.class);
Example.Criteria c1=example.createCriteria();
c1.andLike("stuName","%马%");
System.out.println(studentMapper.selectByExample(example));
姓马的名字全部查出