编辑
2023-11-30
实用工具
00

MongoDB简介

  • MongoDB是一个基于分布式文件存储的数据库
  • 由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
  • MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
  • 它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
  • Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引

应用场景

  • 社交场景,使用 MongoDB存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
  • 游戏场景,使用 MongoDB存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
  • 物流场景,使用 MongoDB存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来
  • 物联网场景,使用 MongoDB存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
  • 视频直播,使用 MongoDB存储用户信息、点赞互动信息等。

这些应用场景中,数据操作方面的共同特点是:

  1. 数据量大
  2. 写入操作频繁(读写都很频繁)
  3. 价值较低的数据,对事务性要求不高

对于这样的数据,我们更适合使用 MongoDB来实现数据的存储。

与关系型数据库术语对照

SQL术语MongoDB术语
databasedatabase
tablecollection
rowdocument
columnfield

Mongodb条件构造器使用

  1. 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)代码演示如下:
  2. Query query = new Query(Criteria.where("id").is(id));
  3. 精准条件:criteria.and("key").is("条件")
  4. 模糊条件:criteria.and("key").regex("条件")
  5. 封装条件:query.addCriteria(criteria)
  6. 大于:Criteria gt = Criteria.where("key").gt("条件")
  7. 小于:Criteria lt = Criteria.where("key").lt("条件")
  8. 范围查询:query.addCriteria(Criteria.where("key").gte("条件").lte("条件")

Query对象方法

  1. addCriteria(Criteria criteria) 添加一个Criteria对象作为查询条件。
  2. limit(int limit) 设置查询结果的限制,指定返回的文档数量
  3. isSorted() 用于检查查询结果是否已排序
  4. skip() 设置查询结果跳过的文档数量
  5. withHint() 配置查询以在执行时使用给定的提示。 hint可以是索引名称或 json Document表示形式
  6. with(Pageable pageable) 在Query实例上设置给定的分页信息。将透明地设置skip和limit以及应用使用Pageable定义的Sort实例。
  7. with(Sort sort)向Query实例添加Sort 排序
  8. getSkip() 获取要跳过的文档数
  9. getLimit() 获取要返回的最大文档数。
  10. comment(String comment)向传播到配置文件日志的查询添加注释
  11. cursorBatchSize(int batchSize) 设置每个响应批次中返回的文档数。 使用 0(零)表示没有限制。负限制会在返回单个批次后关闭游标,指示服务器客户端不会请求后续批次。

Criteria 对象方法

  1. where(String key) 相当于sql的where后输入字段名,key是字段名
  2. and(String key) and方法
  3. is(Object value) 相等 相当于eq
  4. ne(Object value) 不相等
  5. lt(Object value) 小于
  6. lte(Object value) 小于或者等于
  7. gt(Object value) 大于
  8. gte(Object value) 大于或者等于'
  9. in(Object... values) 包含
  10. in(Collection<?> values) 包含
  11. nin(Object... values) 不包含
  12. nin(Collection<?> values) 不包含
  13. mod(Number value, Number remainder) 模运算
  14. all(Object... values) 数据库的数组类型里的元素同时等于values里的值
  15. all(Collection<?> values) 含义如上
  16. size(int size) 查询数组大小为多少
  17. exists(boolean value) 字段内容是否存在 true存在 false不存在
  18. type(int typeNumber) 查找文档值为xx的信息
  19. type(Type... types) 如上
  20. not() 不包含
  21. not( Object value) 不包含
  22. regex(String regex) 正则表达式 可以用来模糊查询,全匹配
  23. regex(String regex, @Nullable String options) options选项
  24. regex(Pattern pattern) is(Object)的语法糖明显表明我们创建了一个正则表达式谓词。
  25. withinSphere(Circle circle) 根据地理坐标操作
  26. elemMatch(Criteria criteria) 包含一个数组字段,该字段至少有一个元素与所有 指定的查询条件
  27. alike(Example<?> sample) 使用给定对象作为模式创建标准。
  28. orOperator(Criteria... criteria) or 相当于sql中的 or(criteria)or(criteria),方法传入多个criteria那这些逻辑之间都是or的关系
  29. norOperator(Criteria... criteria) 返回不满足or逻辑的内容
  30. andOperator(Criteria... criteria) and 方法传入多个criteria那这些逻辑之间都是and的关系

MongoDB搭建

windows-msi形式

官网下载,选择msi的形式下载文件

双击打开,选择Custom 自定义安装目录比如说D

,选择自己想要的地址,一直next就行了

在最后的页面,安装 "Install MongoDB Compass" 不勾选,否则可能要很长时间都一直在执行安装

window-zip形式

官网下载,选择zip的形式下载文件,解压到本地

进入解压后的文件夹,和bin目录同级下创建data和logs文件夹

编辑
2023-11-28
遇到的问题
00

前提

由于业务需要,得对pdf文件进行盖章上传,需要jks文件进行解密获取秘钥,demo将jks文件放在resource中可以正常解密,而将代码结合在主程序中就提示错误Invalid keystore format,前提是密码正常,jks文件正常有效

排查

首先不通过Thread.currentThread().getContextClassLoader().getResource("test.jks")的方式获取文件,先将文件存在其他盘的绝对路径中,进行测试,文件可以正常加载解密

第二步将Thread.currentThread().getContextClassLoader().getResource("test.jks")方法获取路径,复制出来写死在配置项中,加载文件,提示错误Invalid keystore format。

从两个测试来看,首先从第一个测试来看jks文件是正常的,密码正确,第二个测试来看不是类加载的加载问题,路径正常,但是加载器的路径是target/classes路径下面的文件,这个路径的文件有问题,源文件8kb,打开target路径查看,文件是12kb,说明maven打包的时候文件被修改了,导致解密错误

maven过滤文件

在模块的pom文件中添加resources内容进行过滤文件,第一个是resource表示resources目录下都是资源文件需要打包,第二个resouce表示需要过滤stamp/* 目录下的文件,不要替换占位符

xml
<project> <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <excludes> <exclude>stamp/*</exclude> </excludes> <filtering>true</filtering> </resource> </resources> </build> </project>
编辑
2023-11-21
遇到的问题
00

前提

开发过程中一直提示数据库错误,内部类型转换异常,排查字段命名和数据库是否对应,数据类型是否相同都没问题,发现之前实体对象使用@builder类型来构建对象的注解导致的问题

报错

text
### Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'VALUE_TYPE' from result set. Cause: java.sql.SQLException: 无法转换为内部表示

解决方式

  1. 实体对象去除@builder注解,调整之前的业务实体构建方式
  2. 再为实体添加上@AllArgsConstructor @NoArgsConstructor 注解
编辑
2023-11-17
学习记录
00

前提

工作中很多时候需要从Class类中获取属性的值,下面会基础获取,以及结合工作内容

基础获取

java
public class Main { public static void main(String[] args) { Person person = new Person("张三", 25); try { Field nameField = Person.class.getDeclaredField("name"); Field ageField = Person.class.getDeclaredField("age"); // 设置访问权限,如果属性是私有的 nameField.setAccessible(true); ageField.setAccessible(true); // 获取属性值 String name = (String) nameField.get(person); int age = (int) ageField.get(person); System.out.println("姓名:" + name); System.out.println("年龄:" + age); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } }
编辑
2023-11-07
学习记录
00

前提

由于业务需要得为从ftp读取到的pdf加上水印,采用itextpdf依赖的功能

依赖

xml
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.11</version> </dependency> <!-- PDF文件字体 防止中文乱码 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>

代码

我是写在pdf工具类中

java
public static byte[] PDFAddWatermark(byte[] pdfbyte, String waterMarkName) throws Exception { // 每页水印行数 int row = 7; // 每行水印个数 int col = 3; // 旋转角度 float rotation = 30f; byte[] decodeBuffer = pdfbyte; // 读取PDF PdfReader reader = new PdfReader(decodeBuffer); //创建字节数组输出流 ByteArrayOutputStream ous =new ByteArrayOutputStream(); // 创建字节缓冲输出流 BufferedOutputStream bos = new BufferedOutputStream(ous); // 输出的PDF文件内容 PdfStamper stamper = new PdfStamper(reader, bos); BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED); PdfGState gs = new PdfGState(); gs.setFillOpacity(0.2f);//改透明度 gs.setStrokeOpacity(0.4f);//设置笔触字体不透明度 PdfContentByte content; int total = reader.getNumberOfPages();//pdf文件页数 for (int i=0; i<total; i++) { // 在内容上方加水印 content = stamper.getOverContent(i+1); // 在内容下方加水印 // content = stamper.getUnderContent(i+1); //开始写入 content.beginText(); content.setGState(gs); //字体大小 content.setFontAndSize(base, 20); //每页7行,一行3个 for (int j=0; j<col; j++) { for (int k=0; k<row; k++) { float x = reader.getPageSize(i+1).getWidth() / col * j + 90; float y = reader.getPageSize(i+1).getHeight() / row * k; //showTextAligned 方法的参数(文字对齐方式,位置内容,输出水印X轴位置,Y轴位置,旋转角度) content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, rotation); } } // 添加水印文字 content.endText(); } stamper.close(); //添加水印后pdf的base64 byte[] bytes = ous.toByteArray(); ous.close(); bos.close(); reader.close(); return bytes; }