微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mybatis

Mybatis

核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<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/ssm?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
<!--    引入mybatis的映射文件-->
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

搭建框架

0、整体架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJINrjp5-1661318876021)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802103604973.png)]

1、写一个mapper

//类似于以前的dao
public interface UserMapper {
    int insertUser();
}

2、写一个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">
<!--namepace要和mapper类的全路径名保持一致-->
<mapper namespace="mapper.UserMapper">
<!--    1.该文件名称和mapper接口相同名字-->
<!--    int insertUser();-->
<!--    2.方法名和id保持一致-->
    <insert id="insertUser">
        insert into user values (null,'admin',0)
    </insert>
</mapper>

这里有三个对应问题

  • 该映射文件名称和mapper接口类名相同

  • namespace要和mapper类的全路径名保持一致

  • id和mapper类里对应的方法名保持一致

3、将该映射文件配置到该项目的配置文件

mybatis-config.xml

<!--    引入mybatis的映射文件-->
<mappers>
    <mapper resource="mappers/UserMapper.xml"/>
</mappers>

实现方法插入语句

测试类

import mapper.UserMapper;
import org.apache.ibatis.session.sqlSession;
import org.apache.ibatis.session.sqlSessionFactory;
import org.apache.ibatis.session.sqlSessionFactoryBuilder;
import org.junit.Test;
import org.apache.ibatis.io.Resources;

import java.io.IOException;
import java.io.InputStream;

public class MybatisTest {
    @Test
    public void testInsert() throws IOException {
//        获取核心配置文件的输入流
        InputStream is = Resources.getResourceAsstream("mybatis-config.xml");
//        获取sqlSessionFactoryBuilder对象
        sqlSessionFactoryBuilder sqlSessionFactoryBuilder = new sqlSessionFactoryBuilder();
//        获取sqlSessionFactoryBuilder
        sqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//        获取sql的会话对象sqlSession,是mybatis提供的操作数据库的对象
        sqlSession sqlSession = sqlSessionFactory.openSession();
//        获取userMapper的代理实现类对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        调用接口里的方法,他会调用这个方法然后自动执行sql语句
        int result = mapper.insertUser();
//        提交事务
        sqlSession.commit();
        System.out.println(result);
//        关闭sqlSession
        sqlSession.close();
    }

    }

优化

1、自动提交

//        获取sql的会话对象sqlSession(不会自动提交事务),是mybatis提供的操作数据库的对象
//        sqlSession sqlSession = sqlSessionFactory.openSession();
//        获取sql的会话对象sqlSession(会自动提交事务),是mybatis提供的操作数据库的对象
        sqlSession sqlSession = sqlSessionFactory.openSession(true);

2、封装得到会话对象

package util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.sqlSession;
import org.apache.ibatis.session.sqlSessionFactory;
import org.apache.ibatis.session.sqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class sqlSessionUtils {
//    封装会话对象
    public static sqlSession getsqlSession(){

        sqlSession sqlSession = null;
        try {
            //        获取核心配置文件的输入流
            InputStream is  = Resources.getResourceAsstream("mybatis-config.xml");
            //        获取sqlSessionFactoryBuilder对象
            sqlSessionFactoryBuilder sqlSessionFactoryBuilder = new sqlSessionFactoryBuilder();
//        获取sqlSessionFactoryBuilder
            sqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
//        获取sql的会话对象sqlSession(不会自动提交事务),是mybatis提供的操作数据库的对象
//        sqlSession sqlSession = sqlSessionFactory.openSession();
//        获取sql的会话对象sqlSession(会自动提交事务),是mybatis提供的操作数据库的对象
             sqlSession = sqlSessionFactory.openSession(true);

        } catch (IOException e) {
            e.printstacktrace();
        }
        return sqlSession;
    }
}

此时测试方法

    @Test
    public void testInsert() throws IOException {
        sqlSession sqlSession = sqlSessionUtils.getsqlSession();
//        获取userMapper的代理实现类对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.updateUser();
//        关闭sqlSession
        sqlSession.close();
    }

关于如何增删改查

映射关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w72BbV0I-1661318876022)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802152224259.png)]

返回的是一个对象

1、首先要写一个实体类数据库表格对应

User类

package entity;

public class User {
    private int id;
    private String name;
    private int sex;

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getSex() {
        return sex;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex=" + sex +
                '}';
    }
}

2、定义接口方法

//    查询信息UserMapper类
User getUser();

3、写sql语句

<!--    User getUser();-->
<select id="getUser" resultType="entity.User">
    select * from user where id = 1
</select>

4、测试

@Test
public void getUserTest(){
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUser();
    System.out.println(user);

}

5、结果

User{id=1, name=‘aaaa’, sex=0}

返回所有对象

1、定义方法

//    查询所有用户信息
List<User> getAllUser();

2、写sql语句

<select id="getAllUser" resultType="entity.User">
    select * from user
</select>

3、测试类

@Test
public void getAllUserTest(){
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> allUser = mapper.getAllUser();
    allUser.forEach(System.out::println);
}

4、结果

User{id=1, name=‘aaaa’, sex=0}
User{id=2, name=‘lucy’, sex=1}
User{id=3, name=‘jack’, sex=0}

核心配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9GntnAwH-1661318876023)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160523799.png)]

1、environment

image-20220802155610466image-20220802155633639

2、datasource

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2sH6Qjbr-1661318876024)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160059208.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7Ur4mdx-1661318876024)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160208639.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kxWkyXbO-1661318876024)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160234881.png)]

3、typeAliases类型别名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7kII5oWc-1661318876025)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160832869.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FCEnJARX-1661318876025)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802160913865.png)]

若不设置别名,那当前的类型拥有认的别名即类型且不区分大小写

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJLx9LTu-1661318876026)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802161126596.png)]

4、mappers

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EgLhjouj-1661318876026)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802161938011.png)]

mybatis获取参数值的两种方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AxJaGpfs-1661318876027)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802165617043.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NyioasGg-1661318876027)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802170707110.png)]

第一种

  • #{}本质是一个占位符--“?”,所以用这个不用加单引号

  • ${}他不是占位符,如果不加单引号那就是=admin这种会报错,所以加上单引号username=‘admin’,但是这种不能写数字,他会直接运算出来

第二种

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kw6m8Ltu-1661318876027)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802172212892.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9f54ksrn-1661318876028)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802172329073.png)]

第三种 传map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m49yTTuy-1661318876028)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802173542600.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HD8M5OD0-1661318876029)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220802173556991.png)]

第四种 访问User类中的属性

这种就可直接通过属性名访问属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YshwdgoC-1661318876029)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803093917082.png)]

前提要有getset方法

第五种 使用注解@Param(“”)

在mapper接口的参数上使用param注解.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VEJGmXsU-1661318876030)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803094459776.png)]

他还会把这两个参数放到map集合里,自动生成键值,就是param里的参数

他会以两种方式进行存储1.param的value为键值

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

mybatis的各种查询功能

查询的结果是什么类型resultType就写什么类型

resultType里用的是别名,所以里面用大写小写都可以

如果查询出来的结果没用实体类怎么办

1、查询单条数据放map里

那就把resultType=“map”

方法返回值为Map<String,Object>

如果里面某个属性值为null,那这个字段是不会放到map集合里的

2、查询多条数据放到map里

resultType=“map”

方法返回值为List<Map<String,Object>>

3、当查询多条数据,也可以使用第一种的返回值,加上注解@MapKey(设置map集合的键,查询出来的字段)

如果是@MapKey(“id”)

查询出来的所有对象放到一个map里,键值为0 1 2 3.。

{0={},1={},2={}…}

模糊查询

不能直接使用#{}

这样写是错误!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-550Nknx3-1661318876030)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803134007877.png)]

3种正确写法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z84kNurj-1661318876030)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803134838475.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mNyl7Rem-1661318876031)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803135020920.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PthoYviG-1661318876031)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803140327981.png)]

批量删除

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NFDMEtd3-1661318876031)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803141320618.png)]

动态设置表名

表名不能加单引号所以只能用${}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x38OHO8p-1661318876031)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803141729994.png)]

获取自增的主键

//    插入使用自增主键
    void inserUser(User user);
<!--    void inserUser(User user);-->
<!--    使用自增id,并用keyProperty接受自增的id值-->
<!--    但是前提要先给她设置成自增id-->
    <insert id="inserUser" useGeneratedKeys="true" keyProperty="id">
        insert into user  values (null ,#{name},#{sex})
    </insert>
@Test
public void insertUser(){
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = new User("jjj",1);
    mapper.inserUser(user);
    System.out.println(user);
}

ResultMap

通过改名创建对应关系

<resultMap id="BaseResultMap" type="com.ufgov.ur.common.entity.fareportField">
    <id column="SET_YEAR" jdbcType="VARCHAR" property="setYear"/>
</resultMap>
<select id="getfareportFieldList" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from FA_REPORT_FIELD
    <where>
        SET_YEAR = #{setYear,jdbcType=VARCHAR}
    </where>
    order by REPORT_CODE, FIELD_CODE
</select>

第二种是写setting配置

mapUnderscoreToCamelCase 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 true \false False
<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

多对一

处理多对一映射关系

级联关联:

第一种方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sll5RMTy-1661318876032)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803173255901.png)]

第二种方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2SRvWatk-1661318876032)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220803173746962.png)]

association:处理多对一映射关系(处理实体类类型的属性)

property:实体类里关联的另外一个实体类属性

javaType:所关联的实体属于的实体类的类名

实例:

Emp类:

package entity;

public class Emp {
    private int id;
    private String name;
    private Dept dept;

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", dept=" + dept +
                '}';
    }
}

Dept类:

package entity;

public class Dept {
    private int deptId;
    private String deptName;

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

接口里的方法

Emp getEmpAndDeptByStep(@Param("empId") Integer id);

xml配置文件

<!--    Emp getEmpAndDeptByStep(@Param("empId") Integer id);-->
    <resultMap id="empAndDept" type="entity.Emp">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <association property="dept" javaType="entity.Dept">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>
    <select id="getEmpAndDeptByStep" resultMap="empAndDept">
        select id,name,dept_id,dept_name from emp left join dept on emp.id=dept.dept_id where id=#{empId}
    </select>

测试类:

@Test
public void getEmpAndDeptById() {
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    Emp emp = mapper.getEmpAndDeptByStep(1);
    System.out.println(emp);
}

结果:

Emp{id=1, name='事业部', dept=Dept{deptId=1, deptName='啊啊啊'}}

使用分步查询处理多对一

延迟(懒)加载

分步查询可以实现延迟加载.但是必须在核心配置文件中设置全局配置信息.

lazyLoadingEnabled:为true时开启懒加载

aggressiveLazyLoading:为false(认)时按需加载

<settings>
<!--        开启延迟加载-->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!--        按需加载-->
        <setting name="aggressiveLazyLoading" value="false"/>
</settings>

fetchType:在开启了延迟加载的环境中,通过该属性设置当前的分步查询是否使用延迟加载

fetchType=“lazy(懒加载)|eager(立即加载)”

<association property="dept"
             fetchType="lazy"
             select="mapper.UserMapper.getDept"
             column="dept_id">
</association>

一对多

collection处理一对多级联关系

方法

B getBAndA(@Param("id") Integer id);

xml

<resultMap id="aAndb" type="entity.B">
    <id column="id" property="id"></id>
    <result column="dept_id" property="deptId"></result>
    <result column="dept_name" property="deptName"></result>
    <collection property="as" ofType="entity.A">
       <!-- 这里不能用id因为id会和上面的id冲突-->
<!--            <id property="id" column="id"></id>-->
        <result column="name" property="name"></result>
        <result column="dept_id" property="deptId"></result>
    </collection>
</resultMap>
<!--    B getBAndA(@Param("id") Integer id);-->
<select id="getBAndA" resultMap="aAndb">
    select * from b left join a on b.dept_id=a.dept_id where b.id=#{id}
</select>

测试

@Test
public void getAandB2() {
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    B bAndA = mapper.getBAndA(1);
    System.out.println(bAndA);
}

结果

B{id=1, deptId=1, deptName='第一', as=[A{id=0, name='lucy', deptId=1}, A{id=0, name='li', deptId=1}]}

使用分步处理一对多

数据库

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3cqINXU-1661318876033)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220804162924475.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3JRvxNE-1661318876033)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220804162941031.png)]

A类

package entity;

public class A {
    private int id;
    private String name;
    private int deptId;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getDeptId() {
        return deptId;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    @Override
    public String toString() {
        return "A{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", deptId=" + deptId +
                '}';
    }
}

B类:

package entity;

import java.util.List;

public class B {
    private int id;
    private int deptId;
    private String deptName;
    private List<A> as;

    public void setAs(List<A> as) {
        this.as = as;
    }

    public List<A> getAs() {
        return as;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public int getId() {
        return id;
    }

    public int getDeptId() {
        return deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    @Override
    public String toString() {
        return "B{" +
                "id=" + id +
                ", deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", as=" + as +
                '}';
    }
}

接口方法

B getBAndAByOne(@Param("id") Integer id);
List<A> getBAndAByTwo(@Param("deptId") Integer deptId);

xml文件

<resultMap id="AandBByOne" type="entity.B">
        <id property="id" column="id"></id>
        <result column="dept_id" property="deptId"></result>
        <result column="dept_name" property="deptName"></result>
        <association property="as"
                    select="mapper.UserMapper.getBAndAByTwo"
                    column="dept_id">
        </association>
    </resultMap>
    <select id="getBAndAByTwo" resultType="entity.A">
        select * from a where a.dept_id=#{deptId}
    </select>
<!--    B getBAndAByOne(@Param("deptId") Integer id);-->
    <select id="getBAndAByOne" resultMap="AandBByOne">
        select * from b where b.id=#{id}
    </select>

test

@Test
public void getAandBByStep() {
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    B bAndAByOne = mapper.getBAndAByOne(1);
    System.out.println(bAndAByOne);
}

结果

B{id=1, deptId=1, deptName='第一', as=[A{id=0, name='lucy', deptId=1}, A{id=4, name='li', deptId=1}]}

动态sql

https://mybatis.net.cn/dynamic-sql.html

一级缓存和二级缓存

https://www.baidu.com/link?url=l_ZB_1Bk47HUOuBzLDex4IsfAUF61ocbcLWq7yOVloQGBakTcjaZB8RO7VD8pG8hJrd4yngk7dXAKO6JnK-o8FBBVkGe3LWAlCJr-PqZXUe&wd=&eqid=8352787e00003a970000000262eb755e

分页插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aAhOZvah-1661318876033)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220804154917095.png)]

<trim></trim>

https://zhuanlan.zhihu.com/p/425922768

ltMap=“AandBByOne”>
select * from b where b.id=#{id}


test

```java
@Test
public void getAandBByStep() {
    sqlSession sqlSession = sqlSessionUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    B bAndAByOne = mapper.getBAndAByOne(1);
    System.out.println(bAndAByOne);
}

结果

B{id=1, deptId=1, deptName='第一', as=[A{id=0, name='lucy', deptId=1}, A{id=4, name='li', deptId=1}]}

动态sql

https://mybatis.net.cn/dynamic-sql.html

一级缓存和二级缓存

https://www.baidu.com/link?url=l_ZB_1Bk47HUOuBzLDex4IsfAUF61ocbcLWq7yOVloQGBakTcjaZB8RO7VD8pG8hJrd4yngk7dXAKO6JnK-o8FBBVkGe3LWAlCJr-PqZXUe&wd=&eqid=8352787e00003a970000000262eb755e

分页插件

[外链图片转存中…(img-aAhOZvah-1661318876033)]

<trim></trim>

https://zhuanlan.zhihu.com/p/425922768

原文地址:https://www.jb51.cc/wenti/3284362.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐