Spring SpringMVC Mybatis Springboot

Spring

Spring 是一款开源的轻量级 Java 开发框架,旨在提高开发人员的开发效率以及系统的可维护性

Spring,Spring MVC,Spring Boot 之间什么关系? 

        Spring 包含了多个功能模块,其中最重要的是 Spring-Core(主要提供 IoC 依赖注入功能的支持) 模块, Spring 中的其他模块(比如 Spring MVC)的功能实现基本都需要依赖于该模块。

        Spring MVC 是 Spring 中的一个很重要的模块,主要赋予 Spring 快速构建 MVC 架构的 Web 程序的能力

        Spring Boot 旨在简化 Spring 开发(减少配置文件,开箱即用!)

Spring IoC

        IoC(Inversion of Control:控制反转)

IoC 的思想就是将原本在程序中手动创建对象的控制权,交由 Spring 框架来管理

控制:就是对象创建(实例化、管理)的权利

反转:控制权交给外部环境(Spring框架、IoC容器)

Spring Bean 

Bean 就是那些被IoC容器所管理的对象

如何声明一个Bean

  • @Component:通用的注解,可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层,可以使用@Component 注解标注。
  • @Repository : 对应持久层即 Dao 层,主要用于数据库相关操作。
  • @Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao 层。
  • @Controller : 对应 Spring MVC 控制层,主要用于接受用户请求并调用 Service 层返回数据给前端页面

Bean的生命周期

1. Bean对象创建(调用无参构造器)

        Bean 容器找到配置文件中 Spring Bean 的定义。

        Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。

2. 给Bean对象设置属性

        如果涉及到一些属性值 利用 set()方法设置一些属性值
3. Bean对象初始化之前操作(由Bean的后置处理器负责)

        如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行                postProcessBeforeInitialization() 方法

4. Bean对象初始化(需在配置Bean时指定初始化方法)

        如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法
5. Bean对象初始化之后操作(由Bean的后置处理器负责)

        如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行                postProcessAfterInitialization() 方法

6. Bean对象就绪可以使用
7. Bean对象销毁(需在配置Bean时指定销毁方法)

        当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法
8. IOC容器关闭

Bean的后置处理器

Bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行

User类

package com.atguigu.spring.pojo;

/**
 * @author maomao
 * @create 2022-07-23 15:36
 */
public class User {

    private Integer id;
    private String username;
    private String password;
    private Integer age;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("生命周期2:依赖注入");
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public User() {
        System.out.println("生命周期1:实例化");
    }
    public void initMethod(){
        System.out.println("生命周期3:初始化");
    }
    public void destroyMethod(){
        System.out.println("生命周期5:销毁");
    }
}

创建bean的后置处理器

public class MyBeanProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("☆☆☆" + beanName + " = " + bean);
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println("★★★" + beanName + " = " + bean);
        return bean;
    }
}

特别注意的点

        如果Bean的作用域是单例的话 由SpringIOC容器来管理Bean的生命周期

        如果Bean的作用域是Prototype的话 由调用者来维护Bean的生命周期

Spring AOP

AOP(Aspect-Oriented Programming:面向切面编程)

为什么要使用AOP

        问题:非核心代码与业务代码耦合度高, 且分散在各个业务功能方法中不利于维护。

        方法:核心就是:解耦。我们需要把附加功能从业务功能代码中抽取出来

        困难: 要抽取的代码在方法内部,靠以前把子类中的重复代码抽取到父类的方式没法解决。
所以需要引入新的技术

AOP里面的几个概念

        1.横切关注点: 从每个方法中抽取出来的同一类非核心业务

        2. 通知: 每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法

前置通知:在被代理的目标方法前执行 @Before

返回通知:在被代理的目标方法成功结束后执行(寿终正寝)return之后@AfterReturning

异常通知:在被代理的目标方法异常结束后执行(死于非命)catch @AfterThrowing

​后置通知:在被代理的目标方法最终结束后执行(盖棺定论) finally中 @After ​

环绕通知:使用try...catch...finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置 @Around

        3. 切面: 封装通知方法的类

        4. 目标:被代理的对象

        5. 代理:向目标对象应用通知之后创建的代理对象

        6. 连接点: 抽取横切关注点的位置(概念)

总结: AOP 就是抽和套 抽横切关注点封装到切面中他就是一个通知。 在通过切入点定位到连接点 。

        可以在不改变目标对象代码的同时,然后把我们切面中的通知通过切入点表达式套到连接点上,来实现功能的增强。

1.从目标对象中,把非核心业务代码(横切关注点)抽离出来(抽离出横切关注点), 并放入切面(就是一个类)中,封装每一个横切关注点为通知(就是封装为一个方法)。

2.抽出来之后,还要套回去目标对象中。通过切入点pointCut定位到特定的连接点

代理模式

        二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。

        让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

AOP的核心 动态代理

        通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦
        

 静态代理模式

public class CalculatorStaticProxy implements Calculator {
    // 将被代理的目标对象声明为成员变量
    private Calculator target;
    public CalculatorStaticProxy(Calculator target) {
        this.target = target;
    } 
    @Override
    public int add(int i, int j) {
        // 附加功能由代理类中的代理方法来实现
        System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
        // 通过目标对象来实现核心业务逻辑
        int addResult = target.add(i, j);
        System.out.println("[日志] add 方法结束了,结果是:" + addResult);
        return addResult;
    }
}

        静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其他地方也需要附加日志,那还得再声明更多个静态代理类,那就产生了大量重复的代码,日志功能还是分散的,没有统一管理。
        提出进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现。这就需要使用动态代理技术了。

动态代理模式

public class ProxyFactory {
    private Object target;

    public ProxyFactory(Object target) {
        this.target = target;
    }

    public Object getProxy() {
        /**
         * newProxyInstance():创建一个代理实例
         * 其中有三个参数:
         * 1、classLoader:加载动态生成的代理类的类加载器
         * 2、interfaces:目标对象实现的所有接口的class对象所组成的数组
         * 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接
         口中的抽象方法
         */
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
                /**
                 * proxy:代理对象
                 * method:代理对象需要实现的方法,即其中需要重写的方法
                 * args:method所对应方法的参数
                 */
                Object result = null;
                try {
                    System.out.println("[动态代理][日志] " + method.getName() + ",参数:" + Arrays.toString(args));
                    result = method.invoke(target, args);
                    System.out.println("[动态代理][日志] " + method.getName() + ",结果:" + result);
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("[动态代理][日志] " + method.getName() + ",异常:" + e.getMessage());
                } finally {
                    System.out.println("[动态代理][日志] " + method.getName() + ",方法执行完毕");
                }
                return result;
            }
        };
        return Proxy.newProxyInstance(classLoader, interfaces,
                invocationHandler);
    }
}
@Test
public void testDynamicProxy(){
        ProxyFactory factory = new ProxyFactory(new CalculatorLogImpl());
        Calculator proxy = (Calculator) factory.getProxy();
        proxy.div(1,0);
        //proxy.div(1,1);
}

基于注解的AOP

        动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)

        cglib:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口。

        AspectJ:本质上是静态代理,将代理逻辑“织入”被代理的目标类编译得到的字节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解

简历问题

简历问题一:

        为了防止用户恶意刷新接口,使用Redis配合AOP并且结合自定义注解的方式实现接口防刷限流,提高接口稳定性

        首先我自定义了一个注解,注解中设置有两个属性 second MaxCount。 代表多少秒内最多可以访问多少次。

        然后, 定义一个切面类,使用AOP 将规定时间内访问多少次判断的逻辑抽离出横切关注点并且定义为一个通知封装到切面中

        之后,定义一个切入点pointCut,用于匹配当前持有自定义限流注解的执行方法

        之后,编写一个环绕通知,进行短时间内访问多少次的判断,将访问的ip做为key, 访问次数为value,过期时间为自定义注解中的时间值。

        访问时,先通过ip和URL组合作为Key查询Redis缓存,如果查询不到,则将ip和URL组合作为Key,访问次数作为Value,设置过期时间存入Redis中

       如果Redis中有对应的key, 若访问次数小于最大值就将访问次数累加。若是访问超过最大次数,则报错。

SpringMVC

MVC

 SpringMVC

 1. DispatcherServlet前端控制器:整个流程的控制中心,由它调用其他组件处理用户请求。
 2. HandlerMapping处理器映射器:根据用户请求的 URI 找到相应的 Handler 处理器。
 3. HandlerAdapter处理器适配器:根据HandlerMapping找到的 Handler的相关信息,依据特定的规则去执行相关的处理器 Handler。
 4. Handler处理器:负责执行用户的请求,Controller便是处理器。
 5. ModelAndView : 使用 ModelAndView类用来存储处理完后的结果数据,以及显示该数据的视图。
 6. ViewResolver视图解析器:首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。

整个SpringMVC的流程

 1. 用户向服务器发送请求至前端控制器 DispatcherServlet。 
 2. DispathcherServlet 调用HandlerMapping,由此得知由哪个 Handler (Controller)来处理该请求。
 3. HandlerMapping找到具体的处理器,生成处理器对象及处理器拦截器一并返回给 DispathcherServlet。
 4. DispathcherServlet调用 HandlerAdapter 。
 5. HandlerAdapter 经过适配调用具体的Handler,也叫做控制器(Controller)。
 6. Handler 处理完请求后返回 ModelAndView 。
 7. HandlerAdapter 将后端处理器的结果 ModelAndView 反馈给 DispathcherServlet。
 8. DispathcherServlet 将 ModelAndView 传给 视图解析器 ViewResolver 。
 9. ViewResolver 根据 ModelAndView 中的视图名称返回具体的 View 。
 10. DispathcherServlet 将 ModelAndView 中的模型数据填充到视图中,渲染视图。
 11. DispathcherServlet 将结果响应给用户。

一些常用的注解

@RequestMapping用于URL映射

        用在类或者方法上,将URL与该类、该方法映射起来。

属性

path:用来指定请求的 URL ,value 是它的别名。
method:用来指定请求的方式。值为 GET、POST、PUT、DELETE 等。
params :用于指定限制请求参数的条件。
headers:用于指定限制请求消息头的条件。

@PathVariable 、@RequestParam

@PathVariable 的作用为获取路径变量。
@RequestParam 的作用为获取请求参数,也能获取 HTTP 请求体中Content-Type 为 application/x-www-form-urlencoded 编码的内容格式,类似于 id=1&name=ha&age=1 这种格式的数据。    

注解@RequestParam接收的参数是来自HTTP请求体或请求url的QueryString中

@RequestMapping("/user/addUser/{id}")
public void addUser(@PathVariable("id") int id, @RequestParam("name") String name){
    ...
}

@RequestBody

接收的参数来自于 HTTP 报文的 Request Body 中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml 即 JSON、XML 等类型的数据。
 

拦截器

SpringMVC中的拦截器用于拦截控制器方法的执行


SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
postHandle:控制器方法执行之后执行postHandle()
afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()

public class FirstInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

注册拦截器 

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CartInterceptor()).addPathPatterns("/**");
    }

拦截器由HandlerAdaptor调用

Mybatis

整合Mybatis可以基于注解,也可以基于xml文件

整合Mybatis

<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.2.0</version>
</dependency>
<!--导入mysql的驱动-->
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.17</version>
</dependency>

配置连接信息

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.56.128:3306/gulimall_pms
    driver-class-name: com.mysql.jdbc.Driver

基于注解的方式

持久层UserDao接口

import java.util.List;

@Repository
public interface UserDao {
    @Select("select user_id,user_name,user_age from tb_user")
    List<User> findAll();

    @Select("select user_id,user_name,user_age from tb_user where user_id = #{userId}")
    User findById(Integer userId);

    @Insert("insert into tb_user (user_id,user_name,user_age) values (#{userId},#{userName},#{userAge})")
    Integer insert(User user);

    @Update("update tb_user set user_name=#{userName},user_age=#{userAge} where user_id = #{userId}")
    Integer update(User user);

    @Delete("delete from tb_user where user_id=#{userId}")
    Integer delete(Integer userId);
}

配置包扫描:

@MapperScan("com.luo.gulimall.product.dao")

基于xml整合Mybatis

基于注解的Mybatis使用只能应付一些比较简单的数据库查询语句,虽然省事,但在一定程度上也丧失了灵活性,因此,有必要学习一下基于xml整合Mybatis。

编写mapper接口

@Repository
public interface UserDao {
    List<User> findAll();
    
    User findById(Integer userId);

    Integer insert(User user);

    Integer update(User user);

    Integer delete(Integer userId);
}

添加xml映射文件:

在resources目录下创建目录mapper,在mapper目录下创建UserMapper.xml文件:

注意 <mapper namespace="com.luo.gulimall.product.dao.AttrDao"> 一定要与dao包下的接口对应起来。

<?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.luo.gulimall.product.dao.AttrDao">

	<!-- 可根据自己的需求,是否要使用 -->
    <resultMap type="com.luo.gulimall.product.entity.AttrEntity" id="attrMap">
        <result property="attrId" column="attr_id"/>
        <result property="attrName" column="attr_name"/>
        <result property="searchType" column="search_type"/>
        <result property="valueType" column="value_type"/>
        <result property="icon" column="icon"/>
        <result property="valueSelect" column="value_select"/>
        <result property="attrType" column="attr_type"/>
        <result property="enable" column="enable"/>
        <result property="catelogId" column="catelog_id"/>
        <result property="showDesc" column="show_desc"/>
    </resultMap>
    <select id="selectSearchAttrs" resultType="java.lang.Long">
        SELECT attr_id FROM `pms_attr` WHERE attr_id IN
        <foreach collection="attrIds" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
        AND search_type = 1;
    </select>


</mapper>

配置

*mapper-locations: classpath:mapper/Mapper.xml 表示将dao路径下的各个接口与resources/mapper路径下的各个xml文件映射起来,classpath等价于resources目录

mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml

MyBatis的增删改查
 

<!--int insertUser();-->
<insert id="insertUser">
    insert into t_user values(null,'admin','123456',23,'男')
</insert>
<!--int deleteUser();-->
<delete id="deleteUser">
    delete from t_user where id = 7
</delete>
<!--int updateUser();-->
<update id="updateUser">
    update t_user set username='ybc',password='123' where id = 6
</update>

查询一个实体类对象 

<!--User getUserById();-->
<select id="getUserById" resultType="com.atguigu.mybatis.bean.User">
    select * from t_user where id = 2
</select>

查询list集合

<!--List<User> getUserList();-->
<select id="getUserList" resultType="com.atguigu.mybatis.bean.User">
    select * from t_user
</select>

1、查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射关系
resultType:自动映射,用于属性名和表中字段名一致的情况
resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况
 

MyBatis获取参数值的两种方式

${}的本质就是字符串拼接,#{}的本质就是占位符赋值
${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;

但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,
可以自动添加单引号

一般就是使用#{ }

使用@Param标识参数

可以通过@Param注解标识mapper接口中的方法参数
此时,会将这些参数放在map集合中,

以@Param注解的value属性值为键,以参数为值;

以param1,param2...为键,以参数为值;

只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号

User getUserById(@Param("id") int id);
<!--User getUserById(@Param("id") int id);-->
<select id="getUserById" resultType="User">
    select * from t_user where id = #{id}
</select

自定义映射resultMap

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射

resultMap:设置自定义映射
    属性:
        id:表示自定义映射的唯一标识
        type:查询的数据要映射的实体类的类型
    子标签:
        id:设置主键的映射关系
        result:设置普通字段的映射关系
        association:设置多对一的映射关系
        collection:设置一对多的映射关系
        属性:
                property:设置映射关系中实体类中的属性名
                column:设置映射关系中表中的字段名

<resultMap id="userMap" type="User">
    <id property="id" column="id"></id>
    <result property="userName" column="user_name"></result>
    <result property="password" column="password"></result>
    <result property="age" column="age"></result>
    <result property="sex" column="sex"></result>
</resultMap>
<!--List<User> testMohu(@Param("mohu") String mohu);-->
    <select id="testMohu" resultMap="userMap">
<!--select * from t_user where username like '%${mohu}%'-->
    select id,user_name,password,age,sex from t_user where user_name like concat('%',#{mohu},'%')
</select>

整合 Mybatis-Plus

Mybatis-Plus (简称 MP )是由国内 baomidou 组织开源的 Mybatis 的增强工具。在原生 Mybatis 的基础上只做增强不做改变,为简化开发,提高效率而生。

在使用过程中,MP 提供了一套通用的 Mapper 和 Service 操作,只需要继承接口,进行简单的配置便可以进行单表的 CRUD 操作。对于一些复杂的查询,提供了使用数据库字段和 POJO 属性两种方式来构造条件进行查询。此外,它自带乐观锁、性能分析插件、代码生成器和物理分页插件等特色功能。
 

添加依赖

<!--Mybatis-Plus启动器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

配置application.yml:

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.56.128:3306/gulimall_pms
    driver-class-name: com.mysql.jdbc.Driver

mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml

在 MP 中,自动支持实体类字段按照驼峰转下划线形式的进行转换

创建DAO接口

// 继承Mybatis-Plus提供的BaseMapper,提供基础的CRUD及分页方法
@Mapper
public interface AttrDao extends BaseMapper<AttrEntity> {

    List<Long> selectSearchAttrs(@Param("attrIds") List<Long> attrIds);

}

BaseMapper:

 Wrapper是一个条件构造器,作用就是帮我们写 SQL 语句中 where 字段后的那部分内容。

若通用方法无法满足业务需求,你可以在 Mapper 接口中添加自定义方法,同时在 XML 中添加 SQL ,与传统 Mybatis 的写法一致


Service层

接口

public interface AttrService extends IService<AttrEntity> {

    PageUtils queryPage(Map<String, Object> params);

    void saveAttr(AttrVo attr);

    PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type);

    AttrRespVo getAttrInfo(Long attrId);

    void updateAttr(AttrVo attr);

    List<AttrEntity> getRelationAttr(Long attrgroupId);

    void deleteRelation(AttrGroupRelationVo[] vos);

    PageUtils getNoRelationAttr(Map<String, Object> params, Long attrgroupId);

    List<Long> selectSearchAttrs(List<Long> attrIds);

}

 继承 MP 提供的 IService 接口:      

为了避免和 Mapper 接口中的方法混淆,Service 层中的方法命名和 Mapper 有些区别。

增加:insert → save
删除:delete → remove
更新:udpate → update
查询: select → get,list

Config

@Configuration
@EnableTransactionManagement //开启事务功能
@MapperScan("com.luo.gulimall.product.dao")
public class MyBatisConfig {

    //引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        //设置请求的页面大于最大页后操作, true调回首页,false继续请求 默认false
        paginationInterceptor.setOverflow(true);

        //设置最大单页限制数量,默认500条, -1不受限制
        paginationInterceptor.setLimit(1000);

        return paginationInterceptor;

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值