首页 > 其他分享 >Mybatis的五种分页方式详解

Mybatis的五种分页方式详解

时间:2023-06-01 13:35:39浏览次数:39  
标签:10 分页 list userMapper List PageHelper 五种 Mybatis 详解

 



第一种:LIMIT关键字



1,mapper代码
select * from tb_user limit #{pageNo}, #{pageSize}



2,业务层直接调用
public List findByPageInfo(PageInfo info) {
    return userMapper.selectByPageInfo(info);
}



3,优点
灵活性高,可优化空间大
mysql分页语句优化



4,缺点
实现复杂。

 



第二种:RowBounds实现分页

Mybatis提供RowBounds类来实现逻辑分页。RowBounds中有2个字段offset和limit。这种方式获取所有的ResultSet,从ResultSet中的offset位置开始获取limit个记录。但这并不意味着JDBC驱动器会将所有的ResultSet存放在内存,实际上只加载小部分数据到内存,如果需要,再加载部分数据到内存。



1,mapper的xml代码
select * from user



2, dao代码
List<User> selectPage(RowBounds rowBounds);



3, 分页查询
List<User> users = userMapper.selectPage(new RowBounds(5, 10));
   log.info("users:{}",users);

Mybatis的五种分页方式详解_interceptor

查询结果:

users:[User(id=6, username=柳云璇, grade=小三(5)班, age=25, phone=17358053274, sex=女), User(id=7, username=酆雨寒, grade=高一(5)班, age=19, phone=15394214112, sex=女), User(id=8, username=郑春阳, grade=小三(7)班, age=24, phone=15004202411, sex=男)]



4, 优点
使用起来比直接limit简单。



5,缺点
DB压力比较大,因为将结果暂存在db了。

 



第三种:借助数组进行分页(和上面的很相似,只是查询出所有,自己通过subList()进行返回)



1,mapper接口代码
List<Student> queryStudentsByArray();



2,mapper的xml代码
<select id="queryStudentsByArray"  resultMap="studentmapper">
        select * from student
 </select>



3,定义IStuService接口,并且定义分页方法:
List<Student> queryStudentsByArray(int currPage, int pageSize);

通过接收currPage参数表示显示第几页的数据,pageSize表示每页显示的数据条数。

创建IStuService接口实现类StuServiceIml对方法进行实现,对获取到的数组通过currPage和pageSize进行分页:

@Override
    public List<Student> queryStudentsByArray(int currPage, int pageSize) {
        List<Student> students = studentMapper.queryStudentsByArray();
//        从第几条数据开始
        int firstIndex = (currPage - 1) * pageSize;
//        到第几条数据结束
        int lastIndex = currPage * pageSize;
        return students.subList(firstIndex, lastIndex);
    }

通过subList方法,获取到两个索引间的所有数据。



4,最后在controller中创建测试方法:
@ResponseBody
    @RequestMapping("/student/array/{currPage}/{pageSize}")
    public List<Student> getStudentByArray(@PathVariable("currPage") int currPage, @PathVariable("pageSize") int pageSize) {
        List<Student> student = StuServiceIml.queryStudentsByArray(currPage, pageSize);
        return student;
    }

通过用户传入的currPage和pageSize获取指定数据。

他的有点和劣势与上面第中方法类似。

 



第四种:Interceptor 实现



1,自定义Interceptor
@Intercepts({@Signature(type = StatementHandler.class, method = “prepare”, args = {Connection.class, Integer.class})})
public class DefinedPageInterceptor implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		//获取StatementHandler,默认的是RoutingStatementHandler
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		//获取StatementHandler的包装类
		MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
		//分隔代理对象
		while (metaObject.hasGetter("h")) {
			Object obj = metaObject.getValue("h");
			metaObject = SystemMetaObject.forObject(obj);
		}
		while (metaObject.hasGetter("target")) {
			Object obj = metaObject.getValue("target");
			metaObject = SystemMetaObject.forObject(obj);
		}
		//获取查看接口映射的相关信息
		MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
		String mapId = mappedStatement.getId();
		//拦截以ByInterceptor结尾的请求,统一实现分页
		if (mapId.matches(".+ByInterceptor$")) {
			System.out.println("LOG:已触发分页拦截器");
			//获取进行数据库操作时管理参数的Handler
			ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
			// 分页对象需要自己构建,到时候分页方法中要传入 
			//获取请求时的参数
			PageInfo info = (PageInfo) parameterHandler.getParameterObject();
			//获取原始SQL语句
			String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
			//构建分页功能的SQL语句
			String sql = originalSql.trim() + " limit " + info.getPageNum() + ", " + info.getPageSize();
			metaObject.setValue("delegate.boundSql.sql", sql);
		}
		//调用原对象方法,进入责任链下一级
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		//生成Object对象的动态代理对象
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		//如果分页每页数量是统一的,可以在这里进行统一配置,也就无需再传入PageInfo信息了
	}


}



2,添加到mybatis中
@Bean(“oneSqlSessionFactory”)
public SqlSessionFactory sqlSessionFactory() {
    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(dataSource);
    try {
        sqlSessionFactoryBean.setMapperLocations(
        // 设置mybatis的xml所在位置
        new PathMatchingResourcePatternResolver().getResources(“classpath*:mapping/one/*Mapper.xml”));
        //设置自定义的插件
        sqlSessionFactoryBean.setPlugins(new DefinedPageInterceptor());
        return sqlSessionFactoryBean.getObject();
    } catch (Exception e) {
        return null;
    }
}



3,mapper方法
/**
* Interceptor 实现分页,必须以ByInterceptor结构,自定义的Interceptor才能
* 识别出来,并且必须传入PageInfo
* @param pageInfo 自定义的分页
* @return
*/
List selectPageByInterceptor(PageInfo pageInfo);

xml文件

<select id="selectPageByInterceptor" resultType="com.example.demo.mapper.one.User">
        select * from user
    </select>



4, 运行
/**
* 自定义PageInterceptor分页
*/
@Test
public void test04() {
    PageInfo pageInfo=new PageInfo();
    pageInfo.setPageNum(5);
    pageInfo.setPageSize(5);
    List users = userMapper.selectPageByInterceptor(pageInfo);
    log.info(“users:{}”,users);
}

拦截更改后的sql。

Mybatis的五种分页方式详解_java_02

Mybatis的五种分页方式详解_github_03



5, 运行结果

users:[User(id=6, username=柳云璇, grade=小三(5)班, age=25, phone=17358053274, sex=女), User(id=7, username=酆雨寒, grade=高一(5)班, age=19, phone=15394214112, sex=女), User(id=8, username=郑春阳, grade=小三(7)班, age=24, phone=15004202411, sex=男)]

 



第五种:PageHelper (他其实也是第4种的一个实现,用的多,就把他单独描述为一种)



1,官网

官网:https://pagehelper.github.io/

使用方式:https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md



2, 添加pom依赖

com.github.pagehelper pagehelper 最新版本

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.3.2</version>
</dependency>

或者

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>

特别注意,分页和查询直接不能有其他语句

 

要绝对保证PageHelper.startPage和分页查询语句之间不要有任何其他语句,或者在程序结束时增加PageHelper.clearPage();的调用

 



3, 使用

//第一种,RowBounds方式的调用
List<User> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));

//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectIf(1);

//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<User> list = userMapper.selectIf(1);

//第四种,参数方法调用
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(
            @Param("user") User user,
            @Param("pageNum") int pageNum, 
            @Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<User> list = userMapper.selectByPageNumSize(user, 1, 10);

//第五种,参数对象
//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
//有如下 User 对象
public class User {
    //其他fields
    //下面两个参数名和 params 配置的名字一致
    private Integer pageNum;
    private Integer pageSize;
}
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(User user);
}
//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
List<User> list = userMapper.selectByPageNumSize(user);

//第六种,ISelect 接口方式
//jdk6,7用法,创建接口
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//jdk8 lambda用法
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(()-> userMapper.selectGroupBy());

//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy());

//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectLike(user);
    }
});
//lambda
total = PageHelper.count(()->userMapper.selectLike(user));



3). 在 Spring Boot 中配置

Spring Boot 引入 starter 后自动生效,对分页插件进行配置时,在 Spring Boot 对应的配置文件 application.[properties|yaml] 中配置:

properties:

pagehelper.propertyName=propertyValue
pagehelper.reasonable=false
pagehelper.defaultCount=true

yaml:

pagehelper:
  propertyName: propertyValue
  reasonable: false
  defaultCount: true # 分页插件默认参数支持 default-count 形式,自定义扩展的参数,必须大小写一致

支持的默认参数参考: PageHelperStandardProperties.java



4). 分页插件banner设置

为了避免多次配置分页插件导致的错误,配置分页插件后,启动时会输出 banner。

DEBUG [main] -

,------.                           ,--.  ,--.         ,--.
|  .--. '  ,--,--.  ,---.   ,---.  |  '--'  |  ,---.  |  |  ,---.   ,---.  ,--.--.
|  '--' | ' ,-.  | | .-. | | .-. : |  .--.  | | .-. : |  | | .-. | | .-. : |  .--'
|  | --'  \ '-'  | ' '-' ' \   --. |  |  |  | \   --. |  | | '-' ' \   --. |  |
`--'       `--`--' .`-  /   `----' `--'  `--'  `----' `--' |  |-'   `----' `--'
`---'                                   `--'                        is intercepting.

如果在项目启动时输出了多次 banner,就是配置了多次分页插件,根据日志输出的位置排查系统通过哪些方式配置了分页插件。

如果不想在启动时输出 banner,可以通过系统变量或环境变量关闭。

  • 系统变量:-Dpagehelper.banner=false
  • 环境变量:PAGEHELPER_BANNER=false


如何在代码中使用 



分页插件支持以下几种调用方式:

//第一种,RowBounds方式的调用
List<User> list = sqlSession.selectList("x.y.selectIf", null, new RowBounds(0, 10));

//第二种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectIf(1);

//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<User> list = userMapper.selectIf(1);

//第四种,参数方法调用
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(
            @Param("user") User user,
            @Param("pageNum") int pageNum,
            @Param("pageSize") int pageSize);
}
//配置supportMethodsArguments=true
//在代码中直接调用:
List<User> list = userMapper.selectByPageNumSize(user, 1, 10);

//第五种,参数对象
//如果 pageNum 和 pageSize 存在于 User 对象中,只要参数有值,也会被分页
//有如下 User 对象
public class User {
    //其他fields
    //下面两个参数名和 params 配置的名字一致
    private Integer pageNum;
    private Integer pageSize;
}
//存在以下 Mapper 接口方法,你不需要在 xml 处理后两个参数
public interface CountryMapper {
    List<User> selectByPageNumSize(User user);
}
//当 user 中的 pageNum!= null && pageSize!= null 时,会自动分页
List<User> list = userMapper.selectByPageNumSize(user);

//第六种,ISelect 接口方式
//jdk6,7用法,创建接口
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//jdk8 lambda用法
Page<User> page = PageHelper.startPage(1, 10).doSelectPage(()-> userMapper.selectGroupBy());

//也可以直接返回PageInfo,注意doSelectPageInfo方法和doSelectPage
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectGroupBy();
    }
});
//对应的lambda用法
pageInfo = PageHelper.startPage(1, 10).doSelectPageInfo(() -> userMapper.selectGroupBy());

//count查询,返回一个查询语句的count数
long total = PageHelper.count(new ISelect() {
    @Override
    public void doSelect() {
        userMapper.selectLike(user);
    }
});
//lambda
        total=PageHelper.count(()->userMapper.selectLike(user));



下面对最常用的方式进行详细介绍



(一)、RowBounds方式的调用


List<User> list=sqlSession.selectList("x.y.selectIf",null,new RowBounds(1,10));


使用这种调用方式时,你可以使用RowBounds参数进行分页,这种方式侵入性最小,我们可以看到,通过RowBounds方式调用只是使用了这个参数,并没有增加其他任何内容。

分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页

关于这种方式的调用,有两个特殊的参数是针对 RowBounds 的,你可以参看上面的 场景一 和 场景二

注:不只有命名空间方式可以用RowBounds,使用接口的时候也可以增加RowBounds参数,例如:


//这种情况下也会进行物理分页查询
List<User> selectAll(RowBounds rowBounds);


注意: 由于默认情况下的 RowBounds 无法获取查询总数,分页插件提供了一个继承自 RowBounds 的 PageRowBounds,这个对象中增加了 total 属性,执行分页查询后,可以从该属性得到查询总数。

 



(二)、PageHelper.startPage静态方法调用

除了 PageHelper.startPage 方法外,还提供了类似用法的 PageHelper.offsetPage 方法。

在你需要进行分页的 MyBatis 查询方法前调用 PageHelper.startPage 静态方法即可,紧跟在这个方法后的第一个MyBatis 查询方法会被进行分页。

例一:


//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
//紧跟着的第一个select方法会被分页
List<User> list = userMapper.selectIf(1);
assertEquals(2, list.get(0).getId());
assertEquals(10, list.size());
//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>
assertEquals(182, ((Page) list).getTotal());


例二:


//request: url?pageNum=1&pageSize=10
//支持 ServletRequest,Map,POJO 对象,需要配合 params 参数
PageHelper.startPage(request);
//紧跟着的第一个select方法会被分页
List<User> list = userMapper.selectIf(1);

//后面的不会被分页,除非再次调用PageHelper.startPage
List<User> list2 = userMapper.selectIf(null);
//list1
assertEquals(2, list.get(0).getId());
assertEquals(10, list.size());
//分页时,实际返回的结果list类型是Page<E>,如果想取出分页信息,需要强制转换为Page<E>,
//或者使用PageInfo类(下面的例子有介绍)
assertEquals(182, ((Page) list).getTotal());
//list2
assertEquals(1, list2.get(0).getId());
assertEquals(182, list2.size());


例三,使用PageInfo的用法:


//获取第1页,10条内容,默认查询总数count
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectAll();
//用PageInfo对结果进行包装
PageInfo page = new PageInfo(list);
//测试PageInfo全部属性
//PageInfo包含了非常全面的分页属性
assertEquals(1, page.getPageNum());
assertEquals(10, page.getPageSize());
assertEquals(1, page.getStartRow());
assertEquals(10, page.getEndRow());
assertEquals(183, page.getTotal());
assertEquals(19, page.getPages());
assertEquals(1, page.getFirstPage());
assertEquals(8, page.getLastPage());
assertEquals(true, page.isFirstPage());
assertEquals(false, page.isLastPage());
assertEquals(false, page.isHasPreviousPage());
assertEquals(true, page.isHasNextPage());


 



(三)、使用参数方式

想要使用参数方式,需要配置 supportMethodsArguments 参数为 true,同时要配置 params 参数。 例如下面的配置:


<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
        <property name="supportMethodsArguments" value="true"/>
        <property name="params" value="pageNum=pageNumKey;pageSize=pageSizeKey;"/>
	</plugin>
</plugins>


在 MyBatis 方法中:


List<User> selectByPageNumSize(
@Param("user") User user,
@Param("pageNumKey") int pageNum,
@Param("pageSizeKey") int pageSize);


当调用这个方法时,由于同时发现了 pageNumKey 和 pageSizeKey 参数,这个方法就会被分页。params 提供的几个参数都可以这样使用。

除了上面这种方式外,如果 User 对象中包含这两个参数值,也可以有下面的方法:


List<User> selectByPageNumSize(User user);


当从 User 中同时发现了 pageNumKey 和 pageSizeKey 参数,这个方法就会被分页。

注意:pageNum 和 pageSize 两个属性同时存在才会触发分页操作,在这个前提下,其他的分页参数才会生效。

 



(四)、PageHelper安全调用

1. 使用 RowBounds 和 PageRowBounds 参数方式是极其安全的

2. 使用参数方式是极其安全的

3. 使用 ISelect 接口调用是极其安全的

ISelect 接口方式除了可以保证安全外,还特别实现了将查询转换为单纯的 count 查询方式,这个方法可以将任意的查询方法,变成一个 select count(*) 的查询方法。

4. 什么时候会导致不安全的分页?

PageHelper 方法使用了静态的 ThreadLocal 参数,分页参数和线程是绑定的。

只要你可以保证在 PageHelper 方法调用后紧跟 MyBatis 查询方法,这就是安全的。因为 PageHelper 在 finally 代码段中自动清除了 ThreadLocal 存储的对象。

如果代码在进入 Executor 前发生异常,就会导致线程不可用,这属于人为的 Bug(例如接口方法和 XML 中的不匹配,导致找不到 MappedStatement 时), 这种情况由于线程不可用,也不会导致 ThreadLocal 参数被错误的使用。

但是如果你写出下面这样的代码,就是不安全的用法:


PageHelper.startPage(1, 10);
List<User> list;
if(param1 != null){
    list = userMapper.selectIf(param1);
} else {
    list = new ArrayList<User>();
}


这种情况下由于 param1 存在 null 的情况,就会导致 PageHelper 生产了一个分页参数,但是没有被消费,这个参数就会一直保留在这个线程上。当这个线程再次被使用时,就可能导致不该分页的方法去消费这个分页参数,这就产生了莫名其妙的分页。

上面这个代码,应该写成下面这个样子:


List<User> list;
if(param1 != null){
    PageHelper.startPage(1, 10);
    list = userMapper.selectIf(param1);
} else {
    list = new ArrayList<User>();
}


这种写法就能保证安全。

如果你对此不放心,你可以手动清理 ThreadLocal 存储的分页参数,可以像下面这样使用:


List<User> list;
if(param1 != null){
    PageHelper.startPage(1, 10);
    try{
        list = userMapper.selectAll();
    } finally {
        PageHelper.clearPage();
    }
} else {
    list = new ArrayList<User>();
}


这么写很不好看,而且没有必要。

 

标签:10,分页,list,userMapper,List,PageHelper,五种,Mybatis,详解
From: https://blog.51cto.com/lenglingx/6393373

相关文章

  • c++ const详解
    可以使用const的地方就尽量使用const一般引用的类型必须与其所引用对象的类型一致,但是允许一个常量引用绑定到非常量的对象、字面值,甚至是一个一般表达式doublea=42.0;int&b=a;//编译错误,一般引用类型需要与所引用对象类型一致inta=42;constint&b=a;a=......
  • Git分支教程:详解分支创建、合并、删除等操作
    Git是一种强大的分布式版本控制系统,它的分支功能使得团队协作和代码管理变得更加灵活和高效。分支可以让开发人员在不影响主线开发的情况下进行并行开发和实验性工作。本篇博客将详解Git分支的创建、合并、删除等操作,帮助你更好地理解和使用Git的分支功能。分支的基本概念在开......
  • mybatis-plus 批量插入/新增
    建表SETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0;--------------------------------Tablestructureforrewrite_sql------------------------------DROPTABLEIFEXISTS`rewrite_sql`;CREATETABLE`rewrite_sql`(`id`intNOTNULLDEFAULT-1,`stu_......
  • Android HandlerThread详解
    概述AndroidHandlerThread使用,自带Looper消息循环的快捷类。详细原文地址:AndroidHandlerThread详解AndroidHandlerThread详解简书一、准备工作开发环境:jdk1.8EclipseLunaServiceRelease1(4.4.1)运行环境:华为荣耀6(Android4.4)、华为p9(Android7.0)实现功能:Andr......
  • 转:SQLServer详解
    转自:https://juejin.cn/post/71230328148192133481.数据库概念1.1数据库基本概念数据库(DataBase:DB)数据库是是按照数据结构来组织、存储和管理数据的仓库。---->存储和管理数据的仓库数据库管理系统(DatabaseManagementSystem:DBMS)是专门用于管理数据库的计算机系统软......
  • MyBatis之执行器(Excutor)
    MyBatis之执行器(Executor)前面的文章已经介绍了MyBatis的基本使用流程,但我们不能仅仅局限于使用,而是应该去横向扩展,往更深的方向研究。今天就先讲解一下MyBatis中的执行器Executor。我们在CURD的时候,每次都会去获取一个新的SqlSession对象,可以看出来这个接口主要定义类关于CRUD......
  • mybatis
    MyBatis的基本使用MyBatis类中编写://1、加载mybatis的核心配置文件,获取SqlSessionFactoryStringresource="mybatis-config.xml";InputStreaminputStream=Resources.getResourceAsStream(resource);SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().......
  • 解决mybatis-plus查询字段中含有关键词时异常问题
    在使用mybatis-plus查询mysql某张表的数据时,一直告警提示sqlsyntaxerror。于是,把异常提示里的sql语句复制到navicat执行,也提示sqlsyntaxerror。仔细看了下,发有几个字段在navigate里面标示为蓝色(这几个字段为sensitive、status、name),这几个字段在mysql里面是关键词。在查询语......
  • Redis 配置文件的详解
    1.Redis配置文件的位置在linux操作系统中,安装了Redis后,Redis的配置文件位于Redis安装目录下,文件名为redis.conf(例如:Ubuntuapt命令安装,则配置文件位于/etc/redis/redis.conf)。Redis启动时会加载这个配置文件,在运行时按照配置进行工作。网络上的redis.conf配置文......
  • MyBatis+Sharding-JDBC实体类LocalDateTime类型字段查询报SQLFeatureNotSupportedExce
    问题最近协助渠道组开发新需求,封装实现了一个公共模块供不同渠道项目使用。以前各个渠道项目有很多相似的菜单和功能,各自项目里自己的代码实现,本公共模块对新需求的功能点进行抽象,减少重复代码,提高模块复用性和可维护性。目前有2个渠道项目接入了该公共模块,自测时发现其中1个运......