1、分页插件的使用
1.1 在pom.xml中引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.3</version>
</dependency
pom.xml配置:
# 分页配置
pagehelper:
helper-dialect: mysql #使用的数据库. mysql, oracle, sqlite
reasonable: true #开启优化,在分页页码结果没有数据的时候,会显示有数据的页码数据,也就是当当前页<1时,返回第 1 页, 当当前页 > 最大页时, 返回最后一页的数据.
support-methods-arguments: true #是否支持接口参数来传递分页参数,默认false
pageSizeZero: false #表示当 pageSize=0 时返回所有
params: count=countSql
java代码中引入PageHelp.startPage
// 设置分页参数
PageHelper.startPage(pageNum, pageSize);
// 执行分页查询
List<User> userList = userDao.selectUserList();
// 获取分页结果
Page<Emp> p = (Page<Emp>) empList;
//封装PageBean
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
2、批量导入导出流程
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.3</version>
</dependency>
导出代码如下:
@GetMapping("easyExcel/write")
public void easyExcelWrite(HttpServletResponse response){
//查询到数据库中的数据-查询条件
List<UserBaseInfo> users = userBaseInfoService.findUserInfoPageWrite();
OutputStream outputStream = null;
try {
//用户表---文件名已写固定,可变更
String fileName = URLEncoder.encode("用户表", StandardCharsets.UTF_8.name());//文件名
response.setContentType("application/octet-stream;charset=UTF-8");
response.setCharacterEncoding("utf-8");
response.addHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xls");
outputStream = response.getOutputStream();
// 流 , 数据类型 表 数据
EasyExcel.write(outputStream, UserBaseInfo.class).sheet("1").doWrite(users);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.flush();//刷新流:通道中数据全部输出
outputStream.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、redis配置方法
windows配置redis并联通idea
<配置环境>
1、下载redis安装包:
2、双击: redis-server.exe
3、双击: redis-cli.exe
idea中添加redis依赖:
<!--redis数据库连接包-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
properties配置:
### redis配置
# RedisProperties
#redis一共有16(0-15)个数据库,随便给一个
spring.redis.database=11
spring.redis.host=localhost
spring.redis.port=6379
测试:
@SpringBootTest
public class RedisTest{
// redis测试
@Test
public void contextLoads() {
System.out.println("这是一个测试");
Jedis jedis =new Jedis("localhost",6379);
jedis.set("testkey2","value2");
String string =jedis.get("testkey2");
System.out.print(string);
jedis.close();
}
}
打开redis控制台,输入以下命令,测试通过!
4、Oracle自增主键的妙用
自增序列的创建:
create sequence dict_seq -- sequence 序列名
minvalue 101 --最小值
maxvalue 999 --最大值
start with 101 --从101开始计数
increment by 1 -- 每次加几个
CYCLE -- 一直累加,循环
NOCACHE;
修改自增序列的最大最小值:
alter sequence dict_seq minvalue 101;
alter sequence dict_seq maxvalue 999;
删除自增序列:
drop sequence dict_seq;
举例两个我用的示范:(自己根据自己的需求设计合理的序列号)
select ‘D’|| to_char(sysdate,‘yyyymmddHH24MISS’) || dict_seq.nextval from dual; --带秒
select ‘D’|| to_char(sysdate,‘yyyymmddHH24MI’) || dict_seq.nextval from dual; --不带秒
下面截图在mapper.xml中的示范:
<insert id="addUserInfo" parameterType="com.xjc.domain.UserBaseInfo">
<!--
keyProperty:查出的主键值封装给javaBean的哪个属性
order="BEFORE":当前sql在插入sql之前运行
AFTER:当前sql在插入sql之后运行
resultType:查出的数据的返回值类型
BEFORE运行顺序:
先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
在运行插入的sql;就可以取出id属性对应的值
AFTER运行顺序:
先运行插入的sql(从序列中取出新值作为id);
再运行selectKey查询id的sql;
-->
<selectKey keyProperty="id" order="userCode" resultType="String">
<!-- 编写查询主键的sql语句 -->
select 'D'|| to_char(sysdate,'yyyymmddHH24MI') || dict_seq.nextval from dual
</selectKey>
<!-- 插入时的主键是从序列中拿到的 -->
insert into employees(USERCODE,LAST_NAME,EMAIL)
values(#{userCode},#{lastName},#{email})
</insert>
5、枚举类的用法:
/**
* @Description:自定义枚举类
* @Author xie
* @Date 2023/10/30 11:31
*/
public enum ResultStatus {
//个人基本信息表枚举
SUCCESS(0, "操作成功!"),
FAILD(-1, "操作失败!"),
EXCEPTION(-1, "系统异常"),
PARAM_ERROR(10000, "参数错误"),
SYSTEM_ERROR(10001, "系统错误");
Integer code;
String desc;
private ResultStatus(int code,String desc) {
this.code = code;
this.desc = desc;
}
/**
* @Description:调用Code的值返回对应描述
* @Param: [code]
* @Return: java.lang.String
* @Author xie
* @Date 2023/11/3 9:48
*/
public static String getMsgByCode(Integer code){
for (ResultStatus value : ResultStatus.values()) {
if (value.getCode().equals(code)){
return value.getDesc();
}
}
return "";
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
6、swagger的使用:
pom文件配置
<!--swwager配置-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
swagger配置类
@Configuration //配置类
@EnableSwagger2 //swagger注解
public class SwaggerConfig extends WebMvcConfigurationSupport {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations(
"classpath:/static/");
registry.addResourceHandler("swagger-ui.html").addResourceLocations(
"classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
super.addResourceHandlers(registry);
}
//添加用户并配置
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2).groupName(Docket.DEFAULT_GROUP_NAME)
.apiInfo(apiInfo())
.enable(true) //是否启用swagger
.select()
//RequestHandlerSelectors配置要扫描接口的方式
//basePackage()配置要扫描的包
//any()扫描全部
//none()全不扫描
//withClassAnnotation:扫描类上的注解
.apis(RequestHandlerSelectors.basePackage("com.xjc.controller"))
//paths()过滤**路径
//.paths(PathSelectors.any())
.build();//建造者模式
}
//添加用户
@Bean
public Docket docketOne(){
return new Docket(DocumentationType.SWAGGER_2).groupName("王五");
}
//添加用户
@Bean
public Docket docketTwo(){
return new Docket(DocumentationType.SWAGGER_2).groupName("张三");
}
private ApiInfo apiInfo(){
Contact concat = new Contact("小谢","https://www.baidu.com","123456789@qq.com");
return new ApiInfo(
"小谢",
"干饭第一名",
"v1.0",
"https://www.baidu.com",
concat,
"Apache 2.0",
"http//www.apache.org/licenses/LICENSE-2.0",
new ArrayList<>()
);
}
}
访问地址
http://localhost:8080/swagger-ui.html ###端口号+swagger-ui.html
相关注解
@ApiModel
该注解是作用于类上面的,是用来描述类的一些基本信息的。
相关属性:
- value:提供类的一个备用名,如果不设置,默认情况下将使用 class 类的名称
- description:对于类,提供一个详细的描述信息
- parent:这个属性用于描述的是类的一些父类信息
- discriminator:这个属性解释起来比较麻烦,因为这个类主要体现在断言当中
- subTypes:可以通过这个属性,指定我们想要使用的子类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "Id请求体")
public class IdReq{
private String id;
}
@ApiModelProperty
它的作用是添加和操作属性模块的数据。
该注解的使用详情可参见博客:@ApiModelProperty注解的用法
这里我还是以 IdReq 类为例,为该类的属性添加说明
@Data
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(value = "Id请求体")
public class IdReq {
@ApiModelProperty("主键id")
private String id;
}
@ApiOperation
该注解用来对某个方法/接口进行描述
该注解的使用详情可参见博客:Swagger @ApiOperation 注解详解
这里我以 UserController 下的接口为例:
@ApiParam
该注解使用在方法上或者参数上,字段说明,表示对参数的添加元数据(说明或者是否必填等)
相关属性:
name:参数名
value:参数说明
required:是否必填
7、TimeStamp使用和踩坑:
定义规则:
1、 timestamp字段有三个属性:
a) 是否允许NULL。默认为not null。
b) 默认值。可以设定为default CURRENT_TIMESTAMP 或default 某个常量。若定义时缺省,对于第一个出现的timestamp字段,默认为CURRENT_TIMESTAMP,对于其他timestamp字段,默认为 ‘0000-00-00 00:00:00’。 Default可以指定为null,前提是本字段允许null。
比如声明 field2 timestamp null default null。
c) On update CURRENT_TIMESTAMP。是否在更新其他字段时自动将该timestamp字段修改为当前时间戳。对于第一个出现的timestamp字段,默认为On update CURRENT_TIMESTAMP,对于其他timestamp字段,没有此行为。
2、 default CURRENT_TIMESTAMP 和 On update CURRENT_TIMESTAMP 可以同时修饰一个列。被这两个属性任意一个修饰的列定义为timestamps_with_niladic, 一个表中最多只能存在一个定义为timestamps_with_niladic的列。若超过1个,则建表失败。
以上是定义规则,用于定义建表行为.
今天写批量导入,从外部excel导入到数据库中,我的时间设置的是timestamp类型。我没有设置默认值。
在外部excel中,创建时间有值,更新时间没有值,为空。当我插入到数据库的时候,就一只报错:
当我给updatetime一个timestamp类型的时间后,就正常了!
(挺离谱的,具体原因不知道是不是上述的默认值为:NOT NULL的原因)
8、小技巧<list分组遍历到Map中>
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
//1.调用service方法,从数据库拿到字典表的所有数据;假如是两组4条数据
List<DictBO> dictBOList = dictService.findAll();
//2.判断是否为空
if(CollectionUtils.isEmpty(dictBOList)){
return;
}
//3.分组;转化为以typeCode字段作为键,以对应的DictBO对象列表作为值的形式; 现在是两个key,每个key对应的value里面有2条数据
Map<String , List<DictBO>> dictTypeCodeBoMap=
dictBOList.stream().collect(Collectors.groupingBy(DictBO::getTypeCode));
//4.使用迭代器遍历dictTypeCodeBoMap中的每个键值对
Iterator<Map.Entry<String, List<DictBO>>> entries = dictTypeCodeBoMap.entrySet().iterator();
while(entries.hasNext()){
Map.Entry<String, List<DictBO>> entry = entries.next();
//获取当前键值对的键(即typeCode)
String mapKey = entry.getKey();
//获取当前键值对的值(即该typeCode对应的DictBO对象列表)
List<DictBO> details = entry.getValue();
String key ="dev:oracle:querydict"+mapKey;
String value = JSON.toJSONString(details);
redisTemplate.opsForValue().set(key,value,30, TimeUnit.MINUTES);
}
}
9、mapper.xml中的update语句
在一个update语句中,可以批量更新 用begin开始和end结束,注意分号“;”的使用。
BEGIN
update USER_BASE_INFO
set EFFECTIVE = ‘ST02’,
UPDATE_TIME = sysdate
where ID_CARD = #{idCard};
update STUDENT
set NAME=#{name}
where STUDENT_ID=#{studentId};
update CLASS
SET class =#{class}
where user_id= #{userId};
END;