perf: optimize report/appointment query paths and add paging
This commit is contained in:
parent
5b19922fd3
commit
3604b4bb78
@ -3,6 +3,7 @@ package com.petstore.controller;
|
|||||||
import com.petstore.entity.Appointment;
|
import com.petstore.entity.Appointment;
|
||||||
import com.petstore.service.AppointmentService;
|
import com.petstore.service.AppointmentService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -21,19 +22,41 @@ public class AppointmentController {
|
|||||||
public Map<String, Object> list(
|
public Map<String, Object> list(
|
||||||
@RequestParam(required = false) Long userId,
|
@RequestParam(required = false) Long userId,
|
||||||
@RequestParam(required = false) Long storeId,
|
@RequestParam(required = false) Long storeId,
|
||||||
@RequestParam(required = false) String status) {
|
@RequestParam(required = false) String status,
|
||||||
|
@RequestParam(required = false) Integer page,
|
||||||
|
@RequestParam(required = false) Integer pageSize) {
|
||||||
|
|
||||||
|
if (storeId == null && userId == null) {
|
||||||
|
return Map.of("code", 400, "message", "userId或storeId必填");
|
||||||
|
}
|
||||||
|
|
||||||
List<Appointment> appointments;
|
List<Appointment> appointments;
|
||||||
|
boolean usePaging = page != null || pageSize != null;
|
||||||
|
if (usePaging) {
|
||||||
|
int pageNo = page == null ? 1 : page;
|
||||||
|
int size = pageSize == null ? 20 : pageSize;
|
||||||
|
pageNo = Math.max(pageNo, 1);
|
||||||
|
size = Math.min(Math.max(size, 1), 200);
|
||||||
|
Page<Appointment> paged = appointmentService.pageByScope(userId, storeId, status, pageNo - 1, size);
|
||||||
|
return Map.of(
|
||||||
|
"code", 200,
|
||||||
|
"data", paged.getContent(),
|
||||||
|
"page", pageNo,
|
||||||
|
"pageSize", size,
|
||||||
|
"total", paged.getTotalElements(),
|
||||||
|
"totalPages", paged.getTotalPages(),
|
||||||
|
"hasNext", paged.hasNext()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (storeId != null) {
|
if (storeId != null) {
|
||||||
appointments = (status != null && !status.isEmpty())
|
appointments = (status != null && !status.isEmpty())
|
||||||
? appointmentService.getByStoreIdAndStatus(storeId, status)
|
? appointmentService.getByStoreIdAndStatus(storeId, status)
|
||||||
: appointmentService.getByStoreId(storeId);
|
: appointmentService.getByStoreId(storeId);
|
||||||
} else if (userId != null) {
|
} else {
|
||||||
appointments = (status != null && !status.isEmpty())
|
appointments = (status != null && !status.isEmpty())
|
||||||
? appointmentService.getByUserIdAndStatus(userId, status)
|
? appointmentService.getByUserIdAndStatus(userId, status)
|
||||||
: appointmentService.getByUserId(userId);
|
: appointmentService.getByUserId(userId);
|
||||||
} else {
|
|
||||||
return Map.of("code", 400, "message", "userId或storeId必填");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Map.of("code", 200, "data", appointments);
|
return Map.of("code", 200, "data", appointments);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import com.petstore.service.StoreService;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -47,8 +48,22 @@ public class ReportController {
|
|||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public Map<String, Object> list(@RequestParam(required = false) Long storeId,
|
public Map<String, Object> list(@RequestParam(required = false) Long storeId,
|
||||||
@RequestParam(required = false) Long userId) {
|
@RequestParam(required = false) Long userId,
|
||||||
List<Report> reports = reportService.list(storeId, userId);
|
@RequestParam(required = false) Integer page,
|
||||||
|
@RequestParam(required = false) Integer pageSize) {
|
||||||
|
boolean usePaging = page != null || pageSize != null;
|
||||||
|
List<Report> reports;
|
||||||
|
Page<Report> paged = null;
|
||||||
|
Integer pageNo = null;
|
||||||
|
Integer size = null;
|
||||||
|
if (usePaging) {
|
||||||
|
pageNo = Math.max(page == null ? 1 : page, 1);
|
||||||
|
size = Math.min(Math.max(pageSize == null ? 20 : pageSize, 1), 200);
|
||||||
|
paged = reportService.page(storeId, userId, pageNo - 1, size);
|
||||||
|
reports = paged.getContent();
|
||||||
|
} else {
|
||||||
|
reports = reportService.list(storeId, userId);
|
||||||
|
}
|
||||||
// 附加技师名称,并补全图片URL
|
// 附加技师名称,并补全图片URL
|
||||||
List<Map<String, Object>> data = reports.stream().map(r -> {
|
List<Map<String, Object>> data = reports.stream().map(r -> {
|
||||||
Map<String, Object> item = new HashMap<>();
|
Map<String, Object> item = new HashMap<>();
|
||||||
@ -66,6 +81,17 @@ public class ReportController {
|
|||||||
item.put("userId", r.getUserId());
|
item.put("userId", r.getUserId());
|
||||||
return item;
|
return item;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
|
if (usePaging && paged != null) {
|
||||||
|
return Map.of(
|
||||||
|
"code", 200,
|
||||||
|
"data", data,
|
||||||
|
"page", pageNo,
|
||||||
|
"pageSize", size,
|
||||||
|
"total", paged.getTotalElements(),
|
||||||
|
"totalPages", paged.getTotalPages(),
|
||||||
|
"hasNext", paged.hasNext()
|
||||||
|
);
|
||||||
|
}
|
||||||
return Map.of("code", 200, "data", data);
|
return Map.of("code", 200, "data", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,13 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "t_appointment")
|
@Table(
|
||||||
|
name = "t_appointment",
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_appt_store_status_time", columnList = "store_id,status,appointment_time"),
|
||||||
|
@Index(name = "idx_appt_user_status_time", columnList = "user_id,status,appointment_time")
|
||||||
|
}
|
||||||
|
)
|
||||||
public class Appointment {
|
public class Appointment {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@ -7,7 +7,14 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "t_report")
|
@Table(
|
||||||
|
name = "t_report",
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_report_appointment_id", columnList = "appointment_id"),
|
||||||
|
@Index(name = "idx_report_token", columnList = "report_token"),
|
||||||
|
@Index(name = "idx_report_store_user_time", columnList = "store_id,user_id,create_time")
|
||||||
|
}
|
||||||
|
)
|
||||||
public class Report {
|
public class Report {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@ -6,7 +6,12 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "t_service_type")
|
@Table(
|
||||||
|
name = "t_service_type",
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_service_type_store_id", columnList = "store_id")
|
||||||
|
}
|
||||||
|
)
|
||||||
public class ServiceType {
|
public class ServiceType {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@ -6,7 +6,13 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "t_store")
|
@Table(
|
||||||
|
name = "t_store",
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_store_invite_code", columnList = "invite_code"),
|
||||||
|
@Index(name = "idx_store_owner_id", columnList = "owner_id")
|
||||||
|
}
|
||||||
|
)
|
||||||
public class Store {
|
public class Store {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@ -6,7 +6,13 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "t_user")
|
@Table(
|
||||||
|
name = "t_user",
|
||||||
|
indexes = {
|
||||||
|
@Index(name = "idx_user_phone", columnList = "phone"),
|
||||||
|
@Index(name = "idx_user_store_id", columnList = "store_id")
|
||||||
|
}
|
||||||
|
)
|
||||||
public class User {
|
public class User {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.petstore.mapper;
|
package com.petstore.mapper;
|
||||||
|
|
||||||
import com.petstore.entity.Appointment;
|
import com.petstore.entity.Appointment;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -10,4 +12,9 @@ public interface AppointmentMapper extends JpaRepository<Appointment, Long> {
|
|||||||
List<Appointment> findByUserIdAndStatus(Long userId, String status);
|
List<Appointment> findByUserIdAndStatus(Long userId, String status);
|
||||||
List<Appointment> findByStoreId(Long storeId);
|
List<Appointment> findByStoreId(Long storeId);
|
||||||
List<Appointment> findByStoreIdAndStatus(Long storeId, String status);
|
List<Appointment> findByStoreIdAndStatus(Long storeId, String status);
|
||||||
|
|
||||||
|
Page<Appointment> findByUserId(Long userId, Pageable pageable);
|
||||||
|
Page<Appointment> findByUserIdAndStatus(Long userId, String status, Pageable pageable);
|
||||||
|
Page<Appointment> findByStoreId(Long storeId, Pageable pageable);
|
||||||
|
Page<Appointment> findByStoreIdAndStatus(Long storeId, String status, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,29 @@
|
|||||||
package com.petstore.mapper;
|
package com.petstore.mapper;
|
||||||
|
|
||||||
import com.petstore.entity.Report;
|
import com.petstore.entity.Report;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public interface ReportMapper extends JpaRepository<Report, Long> {
|
public interface ReportMapper extends JpaRepository<Report, Long> {
|
||||||
|
Optional<Report> findFirstByAppointmentIdOrderByCreateTimeDesc(Long appointmentId);
|
||||||
|
|
||||||
|
Optional<Report> findFirstByReportToken(String reportToken);
|
||||||
|
|
||||||
|
List<Report> findByStoreIdOrderByCreateTimeDesc(Long storeId);
|
||||||
|
|
||||||
|
List<Report> findByUserIdOrderByCreateTimeDesc(Long userId);
|
||||||
|
|
||||||
|
List<Report> findByStoreIdAndUserIdOrderByCreateTimeDesc(Long storeId, Long userId);
|
||||||
|
|
||||||
|
List<Report> findAllByOrderByCreateTimeDesc();
|
||||||
|
|
||||||
|
Page<Report> findByStoreId(Long storeId, Pageable pageable);
|
||||||
|
|
||||||
|
Page<Report> findByUserId(Long userId, Pageable pageable);
|
||||||
|
|
||||||
|
Page<Report> findByStoreIdAndUserId(Long storeId, Long userId, Pageable pageable);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,10 @@ package com.petstore.service;
|
|||||||
import com.petstore.entity.Appointment;
|
import com.petstore.entity.Appointment;
|
||||||
import com.petstore.mapper.AppointmentMapper;
|
import com.petstore.mapper.AppointmentMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@ -33,6 +37,26 @@ public class AppointmentService {
|
|||||||
return appointmentMapper.findByStoreIdAndStatus(storeId, status);
|
return appointmentMapper.findByStoreIdAndStatus(storeId, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Page<Appointment> pageByScope(Long userId, Long storeId, String status, int pageNo, int pageSize) {
|
||||||
|
Pageable pageable = PageRequest.of(
|
||||||
|
Math.max(pageNo, 0),
|
||||||
|
Math.max(pageSize, 1),
|
||||||
|
Sort.by(Sort.Direction.DESC, "appointmentTime")
|
||||||
|
);
|
||||||
|
boolean hasStatus = status != null && !status.isBlank();
|
||||||
|
if (storeId != null) {
|
||||||
|
return hasStatus
|
||||||
|
? appointmentMapper.findByStoreIdAndStatus(storeId, status, pageable)
|
||||||
|
: appointmentMapper.findByStoreId(storeId, pageable);
|
||||||
|
}
|
||||||
|
if (userId != null) {
|
||||||
|
return hasStatus
|
||||||
|
? appointmentMapper.findByUserIdAndStatus(userId, status, pageable)
|
||||||
|
: appointmentMapper.findByUserId(userId, pageable);
|
||||||
|
}
|
||||||
|
return Page.empty(pageable);
|
||||||
|
}
|
||||||
|
|
||||||
public Appointment getById(Long id) {
|
public Appointment getById(Long id) {
|
||||||
return appointmentMapper.findById(id).orElse(null);
|
return appointmentMapper.findById(id).orElse(null);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,12 +7,15 @@ import com.petstore.mapper.AppointmentMapper;
|
|||||||
import com.petstore.mapper.ReportMapper;
|
import com.petstore.mapper.ReportMapper;
|
||||||
import com.petstore.mapper.UserMapper;
|
import com.petstore.mapper.UserMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -64,23 +67,47 @@ public class ReportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Report getByAppointmentId(Long appointmentId) {
|
public Report getByAppointmentId(Long appointmentId) {
|
||||||
return reportMapper.findAll().stream()
|
if (appointmentId == null) {
|
||||||
.filter(r -> r.getAppointmentId().equals(appointmentId))
|
return null;
|
||||||
.findFirst()
|
}
|
||||||
.orElse(null);
|
return reportMapper.findFirstByAppointmentIdOrderByCreateTimeDesc(appointmentId).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Report getByToken(String token) {
|
public Report getByToken(String token) {
|
||||||
return reportMapper.findAll().stream()
|
if (token == null || token.isBlank()) {
|
||||||
.filter(r -> token.equals(r.getReportToken()))
|
return null;
|
||||||
.findFirst()
|
}
|
||||||
.orElse(null);
|
return reportMapper.findFirstByReportToken(token).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Report> list(Long storeId, Long userId) {
|
public List<Report> list(Long storeId, Long userId) {
|
||||||
return reportMapper.findAll().stream()
|
if (storeId != null && userId != null) {
|
||||||
.filter(r -> storeId == null || storeId.equals(r.getStoreId()))
|
return reportMapper.findByStoreIdAndUserIdOrderByCreateTimeDesc(storeId, userId);
|
||||||
.filter(r -> userId == null || userId.equals(r.getUserId()))
|
}
|
||||||
.collect(Collectors.toList());
|
if (storeId != null) {
|
||||||
|
return reportMapper.findByStoreIdOrderByCreateTimeDesc(storeId);
|
||||||
|
}
|
||||||
|
if (userId != null) {
|
||||||
|
return reportMapper.findByUserIdOrderByCreateTimeDesc(userId);
|
||||||
|
}
|
||||||
|
return reportMapper.findAllByOrderByCreateTimeDesc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Page<Report> page(Long storeId, Long userId, int pageNo, int pageSize) {
|
||||||
|
Pageable pageable = PageRequest.of(
|
||||||
|
Math.max(pageNo, 0),
|
||||||
|
Math.max(pageSize, 1),
|
||||||
|
Sort.by(Sort.Direction.DESC, "createTime")
|
||||||
|
);
|
||||||
|
if (storeId != null && userId != null) {
|
||||||
|
return reportMapper.findByStoreIdAndUserId(storeId, userId, pageable);
|
||||||
|
}
|
||||||
|
if (storeId != null) {
|
||||||
|
return reportMapper.findByStoreId(storeId, pageable);
|
||||||
|
}
|
||||||
|
if (userId != null) {
|
||||||
|
return reportMapper.findByUserId(userId, pageable);
|
||||||
|
}
|
||||||
|
return reportMapper.findAll(pageable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user