Question 1 Query of mongoDb under springboot
data preparation:
public class Student {
@Id
private Long id;
private String name;
/**
* 关联班级ID
*/
private Long classId;
}
public class StudentClass {
@Id
private Long id;
private String className;
private Long schoolId;
}
Search by student name:
Query query = new Query();
//查找方式,表示根据name构造模糊查询
Pattern pattern = Pattern.compile("^.*" + name + ".*$", Pattern.CASE_INSENSITIVE);
//与表中name进行对应
Criteria criteria = Criteria.where("name").regex(pattern);
query.addCriteria(criteria)
//使用mongotemplate进行查询
mongoTemplate.find(query, Student.class);
Query class by student
It can be seen that there is no class field in the student entity, so how to return the class together with the class when querying students?
LookupOperation lookup = LookupOperation.newLookup()
//从表(关联的表)
.from("studentClass")
//主表中与从表相关联的字段
.localField("classId")
//从表与主表相关联的字段
.foreignField("id")
//查询出的从表集合 命名
.as("class");
Aggregation agg = Aggregation.newAggregation(lookup);
mongoTemplate.aggregate(agg, "student", Map.class)
Returned data style:
It can be seen that the data queried from the table will be added to the main table data after such a query, that is to say, in mongoDb, it is not necessary to add an associated entity to the entity, just add the Id of the associated entity.
If you want to add other query conditions, just add criteria like the following
MatchOperation match = Aggregation.match(criteria);
Aggregation agg = Aggregation.newAggregation(lookup, match);
Question 2 The following error occurs when paging
ConverterNotFoundException: No converter found capable of converting from type [java.util.Date] to type [java.sql.Timestamp]
Reason for error:
The following error occurs when performing the issue paging query again. The difference between issue and other entities is that it has a java.sql.Timestamp
type field.
However, there is no problem in the save operation. It is speculated that the time obtained by mongoDb when it obtains the time from the database is unified in the format of java.util.Date
.
That is, the data returned when querying is java.util.Date
.
So what we need to do is to convert the data type into the required type of the object, ie java.sql.Timestamp
when the data is queried.
To achieve this function, the following operations are required to declare the type converter first, indicating that the type conversion is performed after receiving it.
/**
* mongpoDB时间类型转换器
*/
@ReadingConverter
public class TimestampConverter implements Converter<Date, Timestamp> {
@Override
public Timestamp convert(Date source) {
return new Timestamp(source.getTime());
}
}
Then go to config to introduce this converter
@Configuration
public class MongoConfig {
@Bean
public MongoCustomConversions mongoCustomConversions() {
List<Object> converters = new ArrayList<>();
converters.add(new TimestampConverter());
return new MongoCustomConversions(converters);
}
}
Problem three page faults
The paging algorithm written at the beginning is wrong, resulting in the content in the returned page is still the total data. That is, the front-end passes in the paging size and page number, and the back-end still returns all the data.
public Page<Issue> page(String name, Pageable pageable) {
org.springframework.util.Assert.notNull(pageable, "传入的Pageable不能为null");
//构造查询条件进行查询
Query query = new Query();
query.addCriteria(IssueCriteria.containingName(name))
.addCriteria(IssueCriteria.belongToProject(projectId))
.addCriteria(IssueCriteria.beClosed(closed));
List<Project> Issues = mongoTemplate.find(query, Project.class);
long total = mongoTemplate.count(query, Issue.class);
return new PageImpl<Project>(Issues, pageable, total);
}
Obviously, the above algorithm will only return the total data, so the following improvements have been made
package club.yunzhi.nonlycode.repository.criteria;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
/**
* 添加页数查询条件
* 跳过之前页内容,并将返回数限制为页面大小
*/
public class GetTotalPageQuery {
public static Query getPageQuery(Query query, Pageable pageable) {
Query newQuery = query;
newQuery.skip((long) (pageable.getPageNumber() - 1) * pageable.getPageSize())
.limit(pageable.getPageSize());
return newQuery;
}
}
public Page<Issue> page(String name, Long projectId, Boolean closed, Pageable pageable) {
org.springframework.util.Assert.notNull(pageable, "传入的Pageable不能为null");
org.springframework.util.Assert.notNull(projectId, "传入的projectId不能为null");
//构造查询条件进行查询
Query query = new Query();
query.addCriteria(IssueCriteria.containingName(name))
.addCriteria(IssueCriteria.belongToProject(projectId))
.addCriteria(IssueCriteria.beClosed(closed));
//获取总数
long total = mongoTemplate.count(query, Issue.class);
Query pageQuery = GetTotalPageQuery.getPageQuery(query, pageable);
//获取分页情况下具体页信息
List<Issue> issues = mongoTemplate.find(pageQuery, Issue.class);
return new PageImpl<Issue>(issues, pageable, total);
}
Note: The following operation is to directly operate on the address of the query, that is to say, after calling pageQuery, the original incoming query is exactly the same as pagequery, and the paging configuration is also performed, that is, only limited data is returned, so after the query is constructed in the above writing method Just perform count query on it. If you put it at the end, total is always equal to page.size().
.skip((long) (pageable.getPageNumber() - 1) * pageable.getPageSize())
.limit(pageable.getPageSize());
However, according to the above, there will be new problems. For example, the total number of data we currently get is 34, and the size of each page is 5. There are seven pages in total, which is no problem when clicking on the first six pages.
But when the seventh page is clicked, the total number of pages becomes 8 and the eighth page is empty
And the interrupt point in the background shows that the totak data returned each time is always 34, but the totalElements of the page shows the error as follows when the interrupt point is in the foreground (there is no problem with the first five pages). The setting is causing the problem.
So I tried a new method, and later found that query can directly accept pageble variables for paging
query.with(pageable);
After the test, there is no problem, but there is a problem with the connection between pageNumber and the front desk, that is, when the front page paging is 1, the incoming number is 1, but according to mongoTemplate
When querying, the number of the home page is 0, which is different from the rules when querying using reponsitory. Therefore, at present, it can only be operated when the front desk enters and exits the pagenumber, and it can be changed uniformly in the later stage according to the needs.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。