fix:优化行程规划分页查询的逻辑

This commit is contained in:
lulz1 2024-07-08 15:44:45 +08:00
parent c1ef9fa1db
commit 60dc853b57
18 changed files with 384 additions and 157 deletions

View File

@ -163,7 +163,7 @@ public class LoginController {
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
Command.of(UserLoginCommand.class).user(user).sendToQueue(); Command.of(UserLoginCommand.class).user(user).sendToQueue();
user.setSyncTime(LocalDateTime.now()); user.setSyncTime(LocalDateTime.now());
userRepository.save(user); userRepository.saveAndUpdateCache(user);
}); });
} }
} }

View File

@ -36,6 +36,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -159,9 +160,12 @@ public class OrderQuery {
int total = routeOrders.size(); int total = routeOrders.size();
routeApprovalDomainService.checkApprovalPermissions(routeOrders); routeApprovalDomainService.checkApprovalPermissions(routeOrders);
// Set<String> employeeNoSet = routeOrders.stream().filter(it -> it.getApproveOrderNo() != null) Set<String> employeeNoSet = routeOrders.stream().filter(it -> it.getApproveOrderNo() != null)
// .flatMap(it -> Stream.of(it.getUserId(), it.getApproveOrderNo().getCreator())) .flatMap(it -> Stream.of(it.getUserId(), it.getApproveOrderNo().getCreator()))
// .collect(Collectors.toSet()); .collect(Collectors.toSet());
Map<String, User> userMap = userRepository.findByEmployeeNoIn(employeeNoSet)
.stream()
.collect(Collectors.toMap(User::getEmployeeNo, Function.identity()));
List<RouteOrderPageRes> orders = routeOrders List<RouteOrderPageRes> orders = routeOrders
.stream() .stream()
.sorted(statusComparator.thenComparing(RouteOrder::getUpdateTime).reversed()) .sorted(statusComparator.thenComparing(RouteOrder::getUpdateTime).reversed())
@ -171,7 +175,7 @@ public class OrderQuery {
if (legDomainService.checkLocation(routeOrder.getLegItems())) { if (legDomainService.checkLocation(routeOrder.getLegItems())) {
routeRepository.reloadRouteOrderInCache(routeOrder); routeRepository.reloadRouteOrderInCache(routeOrder);
} }
User user = userRepository.findByUserEmployeeNo(routeOrder.getUserId()); User user = userMap.get(routeOrder.getUserId());
return getRouteOrderPageRes(routeOrder, user); return getRouteOrderPageRes(routeOrder, user);
}) })
.toList(); .toList();

View File

@ -15,6 +15,7 @@ import com.chint.infrastructure.echo_framework.command.Command;
import com.chint.infrastructure.util.BaseContext; import com.chint.infrastructure.util.BaseContext;
import com.chint.infrastructure.util.StringCheck; import com.chint.infrastructure.util.StringCheck;
import com.chint.interfaces.rest.data_center.user.dto.UserDataDTO; import com.chint.interfaces.rest.data_center.user.dto.UserDataDTO;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -57,6 +58,7 @@ public class User implements Serializable {
private String gender; private String gender;
private String phoneNumber; private String phoneNumber;
private String password; private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime syncTime; private LocalDateTime syncTime;
private Integer status; private Integer status;
@Transient @Transient

View File

@ -3,16 +3,17 @@ package com.chint.domain.repository;
import com.chint.domain.aggregates.user.User; import com.chint.domain.aggregates.user.User;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
public interface UserRepository { public interface UserRepository {
User findById(Long id); Optional<User> findById(Long id);
User findByUserEmployeeNo(String employeeNo); User findByUserEmployeeNo(String employeeNo);
List<User> findByEmployeeNoIn(Set<String> employeeNoSet); List<User> findByEmployeeNoIn(Set<String> employeeNoSet);
User save(User user); User saveAndUpdateCache(User user);
void saveAll(List<User> userList); void saveAll(List<User> userList);

View File

@ -65,7 +65,7 @@ public class AuthenticateServiceImpl implements AuthenticateService {
//如果数据库不存在该用户需要通过sf信息进行查询并保存到数据库 //如果数据库不存在该用户需要通过sf信息进行查询并保存到数据库
newUser.setCompanyCode(userLoginParam.getCompanyCode()); newUser.setCompanyCode(userLoginParam.getCompanyCode());
httpRequest.loadUserInfo(newUser); httpRequest.loadUserInfo(newUser);
userRepository.save(newUser); userRepository.saveAndUpdateCache(newUser);
newUser.setUserLoginParam(userLoginParam); newUser.setUserLoginParam(userLoginParam);
return getUserLoginResult(newUser); return getUserLoginResult(newUser);
} }

View File

@ -64,12 +64,10 @@ public class LYOrderRecordDomainService {
@ListenTo(command = "LYOrderRecordGenerateCommand", order = 0) @ListenTo(command = "LYOrderRecordGenerateCommand", order = 0)
@Transactional
public void generateFlightRecord(LYOrderRecordGenerateCommand command) { public void generateFlightRecord(LYOrderRecordGenerateCommand command) {
int count = 0;//初始化变量 int count = 0;//初始化变量
int pageSize = 100; // 假设每页大小为10 int pageSize = 100; // 假设每页大小为10
int LoopNum;//需要的循环数 int LoopNum;//需要的循环数
ArrayList<LyOrderFlightRecord> recordsTotal = new ArrayList<>();
do { do {
PageRequest pageResult = PageRequest.of(count, pageSize); PageRequest pageResult = PageRequest.of(count, pageSize);
Page<LyOrderFlightRecord> lyOrderFlightRecordPage = jdbcLyOrderFlightRecord.findAllByStatusIsNull(pageResult); Page<LyOrderFlightRecord> lyOrderFlightRecordPage = jdbcLyOrderFlightRecord.findAllByStatusIsNull(pageResult);
@ -77,34 +75,31 @@ public class LYOrderRecordDomainService {
LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整
//数据 //数据
List<LyOrderFlightRecord> lyOrderFlightRecordPageList = lyOrderFlightRecordPage.toList(); List<LyOrderFlightRecord> lyOrderFlightRecordPageList = lyOrderFlightRecordPage.toList();
recordsTotal.addAll(lyOrderFlightRecordPageList); List<String> routeOrderNoList = lyOrderFlightRecordPageList
.stream()
.map(LyOrderFlightRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderFlightRecord> orderFlightRecordList = lyOrderFlightRecordPageList
.stream()
.map(it -> lyOrderRecordExtensionFactory.createFlightOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveFlightOrderRecordBatch(orderFlightRecordList);
jdbcLyOrderFlightRecord.updateStatusByNullStatus();
count++; count++;
} while (count < LoopNum); } while (count < LoopNum);
//修改数据将状态为null的设置为1 //修改数据将状态为null的设置为1
List<String> routeOrderNoList = recordsTotal
.stream()
.map(LyOrderFlightRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderFlightRecord> orderFlightRecordList = recordsTotal
.stream()
.map(it -> lyOrderRecordExtensionFactory.createFlightOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveFlightOrderRecordBatch(orderFlightRecordList);
jdbcLyOrderFlightRecord.updateStatusByNullStatus();
} }
@ListenTo(command = "LYOrderRecordGenerateCommand", order = 1) @ListenTo(command = "LYOrderRecordGenerateCommand", order = 1)
@Transactional
public void generateHotelRecord(LYOrderRecordGenerateCommand command) { public void generateHotelRecord(LYOrderRecordGenerateCommand command) {
int count = 0;//初始化变量 int count = 0;//初始化变量
int pageSize = 100; // 假设每页大小为10 int pageSize = 100; // 假设每页大小为10
int LoopNum;//需要的循环数 int LoopNum;//需要的循环数
ArrayList<LyOrderHotelRecord> recordsTotal = new ArrayList<>();
do { do {
PageRequest pageResult = PageRequest.of(count, pageSize); PageRequest pageResult = PageRequest.of(count, pageSize);
Page<LyOrderHotelRecord> lyOrderHotelRecordPage = jdbcLyOrderHotelRecord.findAllByStatusIsNull(pageResult); Page<LyOrderHotelRecord> lyOrderHotelRecordPage = jdbcLyOrderHotelRecord.findAllByStatusIsNull(pageResult);
@ -112,34 +107,32 @@ public class LYOrderRecordDomainService {
LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整
//数据 //数据
List<LyOrderHotelRecord> lyOrderHotelRecordPageList = lyOrderHotelRecordPage.toList(); List<LyOrderHotelRecord> lyOrderHotelRecordPageList = lyOrderHotelRecordPage.toList();
recordsTotal.addAll(lyOrderHotelRecordPageList); //修改数据将状态为null的设置为1
List<String> routeOrderNoList = lyOrderHotelRecordPageList
.stream()
.map(LyOrderHotelRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderHotelRecord> orderHotelRecordList = lyOrderHotelRecordPageList
.stream()
.map(it -> lyOrderRecordExtensionFactory.createHotelOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveHotelOrderRecordBatch(orderHotelRecordList);
jdbcLyOrderHotelRecord.updateStatusByNullStatus();
count++; count++;
} while (count < LoopNum); } while (count < LoopNum);
//修改数据将状态为null的设置为1 //修改数据将状态为null的设置为1
List<String> routeOrderNoList = recordsTotal
.stream()
.map(LyOrderHotelRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderHotelRecord> orderHotelRecordList = recordsTotal
.stream()
.map(it -> lyOrderRecordExtensionFactory.createHotelOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveHotelOrderRecordBatch(orderHotelRecordList);
jdbcLyOrderHotelRecord.updateStatusByNullStatus();
} }
@ListenTo(command = "LYOrderRecordGenerateCommand", order = 2) @ListenTo(command = "LYOrderRecordGenerateCommand", order = 2)
@Transactional
public void generateTrainRecord(LYOrderRecordGenerateCommand command) { public void generateTrainRecord(LYOrderRecordGenerateCommand command) {
int count = 0;//初始化变量 int count = 0;//初始化变量
int pageSize = 100; // 假设每页大小为10 int pageSize = 100; // 假设每页大小为10
int LoopNum;//需要的循环数 int LoopNum;//需要的循环数
ArrayList<LyOrderTrainRecord> recordsTotal = new ArrayList<>();
do { do {
PageRequest pageResult = PageRequest.of(count, pageSize); PageRequest pageResult = PageRequest.of(count, pageSize);
Page<LyOrderTrainRecord> lyOrderTrainRecordPage = jdbcLyOrderTrainRecord.findAllByStatusIsNull(pageResult); Page<LyOrderTrainRecord> lyOrderTrainRecordPage = jdbcLyOrderTrainRecord.findAllByStatusIsNull(pageResult);
@ -147,34 +140,32 @@ public class LYOrderRecordDomainService {
LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整
//数据 //数据
List<LyOrderTrainRecord> lyOrderTrainRecordPageList = lyOrderTrainRecordPage.toList(); List<LyOrderTrainRecord> lyOrderTrainRecordPageList = lyOrderTrainRecordPage.toList();
recordsTotal.addAll(lyOrderTrainRecordPageList); List<String> routeOrderNoList = lyOrderTrainRecordPageList
.stream()
.map(LyOrderTrainRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderTrainRecord> orderTrainRecordList = lyOrderTrainRecordPageList
.stream()
.map(it -> lyOrderRecordExtensionFactory.createTrainOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveTrainOrderRecordBatch(orderTrainRecordList);
jdbcLyOrderTrainRecord.updateStatusByNullStatus();
count++; count++;
} while (count < LoopNum); } while (count < LoopNum);
//修改数据将状态为null的设置为1 //修改数据将状态为null的设置为1
List<String> routeOrderNoList = recordsTotal
.stream()
.map(LyOrderTrainRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderTrainRecord> orderTrainRecordList = recordsTotal
.stream()
.map(it -> lyOrderRecordExtensionFactory.createTrainOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveTrainOrderRecordBatch(orderTrainRecordList);
jdbcLyOrderTrainRecord.updateStatusByNullStatus();
} }
@ListenTo(command = "LYOrderRecordGenerateCommand", order = 3) @ListenTo(command = "LYOrderRecordGenerateCommand", order = 3)
@Transactional
public void generateCarRecord(LYOrderRecordGenerateCommand command) { public void generateCarRecord(LYOrderRecordGenerateCommand command) {
int count = 0;//初始化变量 int count = 0;//初始化变量
int pageSize = 100; // 假设每页大小为10 int pageSize = 100; // 假设每页大小为10
int LoopNum;//需要的循环数 int LoopNum;//需要的循环数
ArrayList<LyOrderCarRecord> recordsTotal = new ArrayList<>();
do { do {
PageRequest pageResult = PageRequest.of(count, pageSize); PageRequest pageResult = PageRequest.of(count, pageSize);
Page<LyOrderCarRecord> lyOrderCarRecordPage = jdbcLyOrderCarRecord.findAllByStatusIsNull(pageResult); Page<LyOrderCarRecord> lyOrderCarRecordPage = jdbcLyOrderCarRecord.findAllByStatusIsNull(pageResult);
@ -182,24 +173,24 @@ public class LYOrderRecordDomainService {
LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整
//数据 //数据
List<LyOrderCarRecord> lyOrderCarRecordPageList = lyOrderCarRecordPage.toList(); List<LyOrderCarRecord> lyOrderCarRecordPageList = lyOrderCarRecordPage.toList();
recordsTotal.addAll(lyOrderCarRecordPageList); //修改数据将状态为null的设置为1
List<String> routeOrderNoList = lyOrderCarRecordPageList
.stream()
.map(LyOrderCarRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderCarRecord> orderCarRecordList = lyOrderCarRecordPageList
.stream()
.map(it -> lyOrderRecordExtensionFactory.createCarOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveCarOrderRecordBatch(orderCarRecordList);
jdbcLyOrderCarRecord.updateStatusByNullStatus();
count++; count++;
} while (count < LoopNum); } while (count < LoopNum);
//修改数据将状态为null的设置为1 //修改数据将状态为null的设置为1
List<String> routeOrderNoList = recordsTotal
.stream()
.map(LyOrderCarRecord::getOutApplayOrderNo)
.distinct()
.toList();
List<RouteOrder> routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList);
Map<String, Optional<RouteOrder>> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(),
it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst()));
List<OrderCarRecord> orderCarRecordList = recordsTotal
.stream()
.map(it -> lyOrderRecordExtensionFactory.createCarOrderRecord(it, collect.get(it.getOutApplayOrderNo())))
.toList();
orderDetailDomainService.saveCarOrderRecordBatch(orderCarRecordList);
jdbcLyOrderCarRecord.updateStatusByNullStatus();
} }

View File

@ -1,66 +1,183 @@
package com.chint.infrastructure.echo_framework.repository; package com.chint.infrastructure.echo_framework.repository;
import java.util.List; import java.util.*;
import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public abstract class AbstractGenericRepository<T, ID> { public abstract class AbstractGenericRepository<T, ID> {
protected final GenericCacheRepository<T, ID> cacheRepository; protected final GenericCacheRepository<T, ID> cacheRepository;
protected final JdbcGenericRepository<T, ID> jdbcRepository;
protected final String cachePrefix; protected final String cachePrefix;
protected final Map<String, Function<Set<String>, List<T>>> fieldQueryMap = new HashMap<>();
protected AbstractGenericRepository(GenericCacheRepository<T, ID> cacheRepository,
JdbcGenericRepository<T, ID> jdbcRepository, public AbstractGenericRepository<T, ID> addFieldQueryMap(String fieldPrefix,
String cachePrefix) { Function<Set<String>, List<T>> fieldQuery) {
fieldQueryMap.put(fieldPrefix, fieldQuery);
return this;
}
protected AbstractGenericRepository(GenericCacheRepository<T, ID> cacheRepository) {
this.cacheRepository = cacheRepository; this.cacheRepository = cacheRepository;
this.jdbcRepository = jdbcRepository; this.cachePrefix = getPrefix();
this.cachePrefix = cachePrefix;
} }
public T save(T entity) { public T saveAndUpdateCache(T entity) {
T savedEntity = jdbcRepository.save(entity); save(entity);
updateCache(savedEntity); updateCache(entity);
return savedEntity; return entity;
} }
public T findById(ID id) { public abstract T save(T entity);
T entity = cacheRepository.findFromCache(cachePrefix, id);
if (entity == null) { public Optional<T> findById(ID id, Function<ID, Optional<T>> function) {
Optional<T> optionalEntity = jdbcRepository.findById(id); Optional<T> entity = Optional.ofNullable(cacheRepository.findFromCache(cachePrefix, id));
if (entity.isEmpty()) {
Optional<T> optionalEntity = function.apply(id);
if (optionalEntity.isPresent()) { if (optionalEntity.isPresent()) {
entity = optionalEntity.get(); T finalEntity = optionalEntity.get();
T finalEntity = entity;
CompletableFuture.runAsync(() -> updateCache(finalEntity)); CompletableFuture.runAsync(() -> updateCache(finalEntity));
} }
return optionalEntity;
} }
return entity; return entity;
} }
public <V> T findByField(Function<T, V> fieldGetter, String fieldPrefix) {
ID id = cacheRepository.findIdFromCache(fieldPrefix, fieldGetter.toString()); private Optional<T> findEntity(String fieldPrefix, String fieldValue) {
if (id == null) { return fieldQueryMap.get(fieldPrefix).apply(Set.of(fieldValue)).stream().findFirst();
T entity = findByFieldFromDatabase(fieldGetter);
if (entity != null) {
CompletableFuture.runAsync(() -> updateCache(entity));
}
return entity;
}
return findById(id);
} }
private Optional<T> findByFieldCommon(String fieldPrefix,
String fieldValue, Supplier<ID> idSupplier,
Supplier<Optional<T>> entitySupplier,
Function<ID, Optional<T>> function) {
ID id = idSupplier.get();
if (id == null) {
Optional<T> first = entitySupplier.get();
if (first.isPresent()) {
T entity = first.get();
CompletableFuture.runAsync(() -> {
updateCache(entity);
updateFieldCache(fieldPrefix, fieldValue, getPrimaryKeys(entity));
});
}
return first;
}
return function.apply(id);
}
public <V> Optional<T> findByField(String fieldPrefix, String fieldValue) {
return findByField(fieldPrefix, fieldValue, this::findByIdFromDB);
}
// public <V> Optional<T> findByField(String fieldPrefix, Function<T, V> fieldGetter, Function<ID, Optional<T>> function) {
// return findByFieldCommon(
// fieldPrefix, fieldGetter.apply()
// () -> cacheRepository.findIdFromCache(cachePrefix, fieldPrefix, fieldGetter.toString()),
// () -> findEntity(fieldPrefix, fieldGetter.toString()), (id) -> findById(id, function);
// );
// }
public Optional<T> findByField(String fieldPrefix, String fieldValue, Function<ID, Optional<T>> function) {
return findByFieldCommon(
fieldPrefix, fieldValue,
() -> cacheRepository.findIdFromCache(cachePrefix, fieldPrefix, fieldValue),
() -> findEntity(fieldPrefix, fieldValue),
(id) -> findById(id, function)
);
}
public List<T> findByIdsIn(Set<ID> ids) {
// Step 1: Get data from cache
List<T> inCacheList = cacheRepository.findBatchByIds(cachePrefix, ids);
// Step 2: Identify cached IDs and missing IDs
List<ID> cachedIds = inCacheList.stream()
.filter(Objects::nonNull)
.map(this::getPrimaryKeys)
.map(Object::toString)
.map(id -> (ID) id)
.toList();
List<ID> missingIds = ids.stream()
.filter(Objects::nonNull)
.filter(id -> !cachedIds.contains(id))
.toList();
// Step 3: Get data from database for missing IDs and update cache
if (!missingIds.isEmpty()) {
List<T> fetchedList = findByIdsInFromDB(new HashSet<>(missingIds));
inCacheList.addAll(fetchedList);
CompletableFuture.runAsync(() -> fetchedList.forEach(this::updateCache));
}
// Step 4: Return the complete list
return inCacheList;
}
public List<T> findByFieldsIn(String fieldPrefix,
Set<String> fieldValues,
Function<T, String> fieldGetter,
Function<Set<String>, List<T>> fieldQueryMethod) {
// Step 1: Get IDs from cache
Set<ID> ids = new HashSet<>(cacheRepository.findIdsFromCache(cachePrefix, fieldPrefix, fieldValues));
// Step 2: Get data from cache using IDs
List<T> inCacheList = cacheRepository.findBatchByIds(cachePrefix, ids);
// Step 3: Identify cached IDs and missing IDs
List<String> cachedFields = inCacheList.stream()
.filter(Objects::nonNull)
.map(fieldGetter)
.toList();
Set<String> missingFields = fieldValues.stream()
.filter(field -> !cachedFields.contains(field))
.collect(Collectors.toSet());
// Step 4: Get data from database for missing fields and update cache
if (!missingFields.isEmpty()) {
List<T> fetchedList = fieldQueryMethod.apply(missingFields);
inCacheList.addAll(fetchedList);
CompletableFuture.runAsync(() -> {
fetchedList.forEach(this::updateCache);
fetchedList.forEach(it -> updateFieldCache(fieldPrefix, fieldGetter.apply(it), getPrimaryKeys(it)));
});
}
// Step 5: Return the complete list
return inCacheList;
}
public List<T> findByFieldsIn(String fieldPrefix,
Set<String> fieldValues,
Function<T, String> fieldGetter) {
return findByFieldsIn(fieldPrefix, fieldValues, fieldGetter, fieldQueryMap.get(fieldPrefix));
}
protected abstract Optional<T> findByIdFromDB(ID id);
protected abstract List<T> findByIdsInFromDB(Set<ID> ids);
//通过主键实现该方法
protected abstract ID getPrimaryKeys(T entity);
protected abstract String getPrefix(); protected abstract String getPrefix();
protected abstract <V> T findByFieldFromDatabase(V fieldValue); public void updateCache(T entity) {
beforeUpdateCache();
cacheRepository.cacheEvict(cachePrefix, getPrimaryKeys(entity));
cacheRepository.cache(cachePrefix, getPrimaryKeys(entity), entity);
}
protected abstract List<T> findByFieldInFromDatabase(List<String> fieldValueList); protected abstract String beforeUpdateCache();
protected abstract void updateCache(T entity);
protected void updateFieldCache(String fieldName, String fieldValue, ID id) { protected void updateFieldCache(String fieldName, String fieldValue, ID id) {
cacheRepository.cacheEvictFieldToId(fieldName, fieldValue); cacheRepository.cacheEvictFieldToId(cachePrefix, fieldName, fieldValue);
cacheRepository.cacheFieldToId(fieldName, fieldValue, id); cacheRepository.cacheFieldToId(cachePrefix, fieldName, fieldValue, id);
} }
protected String getFieldPrefix(String fieldName) { protected String getFieldPrefix(String fieldName) {

View File

@ -1,10 +1,11 @@
package com.chint.infrastructure.echo_framework.repository; package com.chint.infrastructure.echo_framework.repository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set;
public class GenericCacheRepository<T, ID> { public class GenericCacheRepository<T, ID> {
@ -13,6 +14,7 @@ public class GenericCacheRepository<T, ID> {
private final RedisTemplate<String, ID> redisTemplateId; private final RedisTemplate<String, ID> redisTemplateId;
private final Class<T> entityType; private final Class<T> entityType;
private final Class<ID> idType; private final Class<ID> idType;
private final Duration cacheExpiration; // 添加缓存失效时间
public GenericCacheRepository(RedisTemplate<String, T> redisTemplate, public GenericCacheRepository(RedisTemplate<String, T> redisTemplate,
RedisTemplate<String, ID> redisTemplateId, RedisTemplate<String, ID> redisTemplateId,
@ -22,15 +24,20 @@ public class GenericCacheRepository<T, ID> {
this.redisTemplateId = redisTemplateId; this.redisTemplateId = redisTemplateId;
this.entityType = entityType; this.entityType = entityType;
this.idType = idType; this.idType = idType;
this.cacheExpiration = Duration.ofHours(6L);
} }
private String getKey(String prefix, Object value) { private String getKey(String prefix, Object value) {
return prefix + "::" + value; return prefix + "::" + value;
} }
private String getKey(String prefix, String fieldPrefix, Object value) {
return prefix + "::" + fieldPrefix + "::" + value;
}
public T cache(String prefix, ID id, T entity) { public T cache(String prefix, ID id, T entity) {
String key = getKey(prefix, id); String key = getKey(prefix, id);
redisTemplate.opsForValue().set(key, entity); redisTemplate.opsForValue().set(key, entity, cacheExpiration);
return entity; return entity;
} }
@ -44,29 +51,48 @@ public class GenericCacheRepository<T, ID> {
return redisTemplate.opsForValue().get(key); return redisTemplate.opsForValue().get(key);
} }
public List<T> cacheBatchByIds(String prefix, List<ID> ids) { public List<T> findBatchByIds(String prefix, Set<ID> ids) {
List<String> keys = ids.stream().map(id -> getKey(prefix, id)).toList(); List<String> keys = ids.stream().map(id -> getKey(prefix, id)).toList();
return redisTemplate.opsForValue().multiGet(keys); return redisTemplate.opsForValue().multiGet(keys);
} }
public ID cacheFieldToId(String fieldPrefix, String fieldValue, ID id) { public ID cacheFieldToId(String prefix, String fieldPrefix,
String key = getKey(fieldPrefix, fieldValue); String fieldValue, ID id) {
redisTemplateId.opsForValue().set(key, id); String key = getKey(prefix, fieldPrefix, fieldValue);
redisTemplateId.opsForValue().set(key, id, cacheExpiration);
return id; return id;
} }
public ID findIdFromCache(String fieldPrefix, String fieldValue) { public void cacheEvictFieldToId(String prefix, String fieldPrefix, String fieldValue) {
String key = getKey(fieldPrefix, fieldValue); String key = getKey(prefix, fieldPrefix, fieldValue);
redisTemplateId.delete(key);
}
public void cacheFieldsToIdsBatch(String prefix, String fieldPrefix,
Map<String, ID> fieldValuesToIds) {
fieldValuesToIds.forEach((fieldValue, id) -> {
String redisKey = getKey(prefix, fieldPrefix, fieldValue);
// 将ID存储到Redis列表中假设列表中每个位置存储一个ID对象
redisTemplateId.opsForList().rightPush(redisKey, id);
redisTemplateId.expire(redisKey, cacheExpiration);
});
}
public void cacheEvictFieldsToIdsBatch(String prefix, String fieldPrefix, Set<String> fieldValues) {
List<String> keys = fieldValues.stream().map(it -> getKey(prefix, fieldPrefix, it)).toList();
redisTemplateId.delete(keys);
}
public ID findIdFromCache(String prefix, String fieldPrefix,
String fieldValue) {
String key = getKey(prefix, fieldPrefix, fieldValue);
return redisTemplateId.opsForValue().get(key); return redisTemplateId.opsForValue().get(key);
} }
public List<ID> findIdsFromCache(String fieldPrefix, List<String> fieldValueList) { public List<ID> findIdsFromCache(String prefix, String fieldPrefix,
List<String> keys = fieldValueList.stream().map(fieldValue -> getKey(fieldPrefix, fieldValue)).toList(); Set<String> fieldValueList) {
List<String> keys = fieldValueList.stream().map(fieldValue -> getKey(prefix, fieldPrefix, fieldValue))
.toList();
return redisTemplateId.opsForValue().multiGet(keys); return redisTemplateId.opsForValue().multiGet(keys);
} }
public void cacheEvictFieldToId(String fieldPrefix, String fieldValue) {
String key = getKey(fieldPrefix, fieldValue);
redisTemplateId.delete(key);
}
} }

View File

@ -8,9 +8,4 @@ import java.util.Optional;
@Repository @Repository
public interface JdbcGenericRepository<T, ID> extends CrudRepository<T, ID> { public interface JdbcGenericRepository<T, ID> extends CrudRepository<T, ID> {
Optional<T> findById(ID id);
List<T> findAll();
List<T> findByIdIn(List<ID> ids);
} }

View File

@ -230,7 +230,7 @@ public class RouteRepositoryImpl implements RouteRepository {
routeOrder.setUpdateTime(LocalDateTime.now()); routeOrder.setUpdateTime(LocalDateTime.now());
} }
String redisKey = "TemporaryRouteOrder:" + approveOrderNo.getSysCode() + "-" + approveOrderNo.getFakeOrderNo(); String redisKey = "TemporaryRouteOrder:" + approveOrderNo.getSysCode() + "-" + approveOrderNo.getFakeOrderNo();
redisTemplate.opsForValue().set(redisKey, routeOrder, 7L, TimeUnit.DAYS); redisTemplate.opsForValue().set(redisKey, routeOrder, 15L, TimeUnit.DAYS);
return routeOrder; return routeOrder;
} }
} }

View File

@ -1,51 +1,105 @@
package com.chint.infrastructure.repository; package com.chint.infrastructure.repository;
import com.chint.domain.aggregates.user.User; import com.chint.domain.aggregates.user.User;
import com.chint.domain.exceptions.CommandException;
import com.chint.domain.repository.UserRepository; import com.chint.domain.repository.UserRepository;
import com.chint.infrastructure.echo_framework.repository.AbstractGenericRepository;
import com.chint.infrastructure.echo_framework.repository.GenericCacheRepository;
import com.chint.infrastructure.repository.cache.CacheUserRepository;
import com.chint.infrastructure.repository.jdbc.JdbcUserRepository; import com.chint.infrastructure.repository.jdbc.JdbcUserRepository;
import com.chint.interfaces.rest.base.PostRequest;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
@Repository @Repository
public class UserRepositoryImpl implements UserRepository { public class UserRepositoryImpl extends AbstractGenericRepository<User, Long> implements UserRepository {
@Autowired @Autowired
private JdbcUserRepository jdbcUserRepository; private JdbcUserRepository jdbcUserRepository;
@Override @Autowired
public User findById(Long id) { private CacheUserRepository cacheUserRepository;
return null;
@Autowired
private RedisTemplate<String, User> redisTemplate;
@Autowired
private RedisTemplate<String, Long> redisTemplateId;
@Autowired
private PostRequest postRequest;
@Autowired
public UserRepositoryImpl(JdbcUserRepository jdbcUserRepository,
CacheUserRepository cacheUserRepository,
RedisTemplate<String, User> redisTemplate,
RedisTemplate<String, Long> redisTemplateId) {
super(new GenericCacheRepository<>(redisTemplate, redisTemplateId, User.class, Long.class));
this.jdbcUserRepository = jdbcUserRepository;
this.cacheUserRepository = cacheUserRepository;
}
@PostConstruct
public void init() {
this.addFieldQueryMap("EmployeeNo", (set) -> jdbcUserRepository.findByEmployeeNoIn(set));
}
@Override
public Optional<User> findById(Long id) {
return findById(id, (userId) -> jdbcUserRepository.findById(userId));
}
@Override
protected List<User> findByIdsInFromDB(Set<Long> longs) {
return jdbcUserRepository.findByUserIdIn(longs);
}
@Override
protected Long getPrimaryKeys(User entity) {
return entity.getUserId();
}
@Override
protected String getPrefix() {
return "User";
}
@Override
protected String beforeUpdateCache() {
return "";
} }
@Cacheable(value = "UserEmployeeNoCache", key = "#employeeNo")
@Override @Override
public User findByUserEmployeeNo(String employeeNo) { public User findByUserEmployeeNo(String employeeNo) {
return jdbcUserRepository.findByEmployeeNo(employeeNo); return this.findByField("EmployeeNo", employeeNo)
.orElseThrow(() -> new CommandException("Employee Not Found"));
} }
@Override @Override
public List<User> findByEmployeeNoIn(Set<String> employeeNoSet) { public List<User> findByEmployeeNoIn(Set<String> employeeNoSet) {
return List.of(); return this.findByFieldsIn("EmployeeNo", employeeNoSet,
User::getEmployeeNo,
(set) -> jdbcUserRepository.findByEmployeeNoIn(employeeNoSet));
} }
@CacheEvict(value = "UserEmployeeNoCache", key = "#user.employeeNo")
@Override @Override
public User save(User user) { public User save(User user) {
User byEmployeeNo = jdbcUserRepository.findByEmployeeNo(user.getEmployeeNo());
if (byEmployeeNo != null) {
user.setUserId(byEmployeeNo.getUserId());
}
return jdbcUserRepository.save(user); return jdbcUserRepository.save(user);
} }
@Override
protected Optional<User> findByIdFromDB(Long aLong) {
return jdbcUserRepository.findById(aLong);
}
@Override @Override
public void saveAll(List<User> userList) { public void saveAll(List<User> userList) {
jdbcUserRepository.saveAll(userList); jdbcUserRepository.saveAll(userList);

View File

@ -0,0 +1,10 @@
package com.chint.infrastructure.repository.cache;
import org.springframework.stereotype.Repository;
@Repository
public class CacheUserRepository {
}

View File

@ -6,12 +6,17 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.List; import java.util.List;
@Repository @Repository
public interface JdbcUserRepository extends CrudRepository<User, Long> { public interface JdbcUserRepository extends CrudRepository<User, Long> {
User findByEmployeeNo(String employeeNo); User findByEmployeeNo(String employeeNo);
List<User> findByEmployeeNoIn(Collection<String> employeeNo);
List<User> findByUserIdIn(Collection<Long> userId);
List<User> findByStatus(Integer status); List<User> findByStatus(Integer status);
List<User> findByStatusIsNull(); List<User> findByStatusIsNull();

View File

@ -111,7 +111,7 @@ public class BatchUserWorker {
} else { } else {
user.setStatus(1); user.setStatus(1);
} }
userRepository.save(user); userRepository.saveAndUpdateCache(user);
} }
} }
@ -228,7 +228,7 @@ public class BatchUserWorker {
cTripUserSaveRequest.saveUserToCTrip(user); cTripUserSaveRequest.saveUserToCTrip(user);
// 发送保存用户同步时间 // 发送保存用户同步时间
user.setSyncTime(LocalDateTime.now()); user.setSyncTime(LocalDateTime.now());
userRepository.save(user); userRepository.saveAndUpdateCache(user);
} }

View File

@ -187,7 +187,7 @@ public class UserHttpRequestImpl implements UserHttpRequest {
.ifPresent(it -> { .ifPresent(it -> {
User byUserEmployeeNo = userRepository.findByUserEmployeeNo(user.getEmployeeNo()); User byUserEmployeeNo = userRepository.findByUserEmployeeNo(user.getEmployeeNo());
if (byUserEmployeeNo == null) { if (byUserEmployeeNo == null) {
userRepository.save( userRepository.saveAndUpdateCache(
getDataFromUserSFData(user, it) getDataFromUserSFData(user, it)
); );
} }
@ -224,7 +224,7 @@ public class UserHttpRequestImpl implements UserHttpRequest {
getDataFromUserSFData(user, userDataDTOList.get(0)); getDataFromUserSFData(user, userDataDTOList.get(0));
} }
return userRepository.save(user); return userRepository.saveAndUpdateCache(user);
} }
public String belongDeport(String employeeNo, String accountCompanyName) { public String belongDeport(String employeeNo, String accountCompanyName) {
@ -248,7 +248,7 @@ public class UserHttpRequestImpl implements UserHttpRequest {
List<UserDepartmentInfo> userDepartmentInfos = userDepartmentInfoList.stream().distinct().toList(); List<UserDepartmentInfo> userDepartmentInfos = userDepartmentInfoList.stream().distinct().toList();
if (userDepartmentInfos.size() < userDepartmentInfoList.size()) { if (userDepartmentInfos.size() < userDepartmentInfoList.size()) {
user.setUserDepartmentInfoList(userDepartmentInfos); user.setUserDepartmentInfoList(userDepartmentInfos);
userRepository.save(user); userRepository.saveAndUpdateCache(user);
} }
} }

View File

@ -250,7 +250,7 @@ public class CTripTest {
@Test @Test
void search() { void search() {
BaseContext.setCurrentUser(user); BaseContext.setCurrentUser(user);
SearchOrderResponse response = orderSearchRequest.searchOrderResponseByOrderId("32055893290"); SearchOrderResponse response = orderSearchRequest.searchOrderResponseByOrderId("33303376379");
System.out.println(response); System.out.println(response);
} }

View File

@ -2,6 +2,8 @@ package com.chint;
import com.chint.domain.aggregates.order.RouteOrder; import com.chint.domain.aggregates.order.RouteOrder;
import com.chint.domain.aggregates.user.User;
import com.chint.domain.repository.UserRepository;
import com.chint.infrastructure.cache.RouteCacheManage; import com.chint.infrastructure.cache.RouteCacheManage;
import com.chint.infrastructure.cache.RouteCacheService; import com.chint.infrastructure.cache.RouteCacheService;
import com.chint.interfaces.rest.ctrip.CTripLocationHttpRequest; import com.chint.interfaces.rest.ctrip.CTripLocationHttpRequest;
@ -12,6 +14,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import java.util.List; import java.util.List;
import java.util.Set;
@SpringBootTest @SpringBootTest
public class CacheTest { public class CacheTest {
@ -25,6 +28,11 @@ public class CacheTest {
@Autowired @Autowired
private RouteCacheManage routeCacheManage; private RouteCacheManage routeCacheManage;
@Autowired
private UserRepository userRepository;
private Gson gson = new Gson();
// @Test // @Test
public void getAllRouteOrderById(){ public void getAllRouteOrderById(){
List<String> keys = List.of("RouteOrders::900","RouteOrders::918"); List<String> keys = List.of("RouteOrders::900","RouteOrders::918");
@ -51,4 +59,18 @@ public class CacheTest {
public void cancelCache(){ public void cancelCache(){
routeCacheService.invalidateRouteCache(null); routeCacheService.invalidateRouteCache(null);
} }
@Test
public void findUserByEmployeeNo(){
User byUserEmployeeNo = userRepository.findByUserEmployeeNo("230615020");
System.out.println(byUserEmployeeNo);
System.out.println(userRepository.findByEmployeeNoIn(Set.of("230615020", "231116011")));
System.out.println(userRepository.findById(1L));
byUserEmployeeNo.setPassword("123123123123123213123");
userRepository.saveAndUpdateCache(byUserEmployeeNo);
System.out.println(userRepository.findById(1L));
}
} }

View File

@ -324,10 +324,10 @@ class RouteApplicationTests {
@Test @Test
void loginSignProd() { void loginSignProd() {
String sfno = "210506025"; String sfno = "231026051";
String syscode = "ANFSSC"; String syscode = "FSSC";
String billcode = "CLS24062700018"; String billcode = "CLSQ240225000099";
String companycode = "正泰安能数字能源(浙江)股份有限公司"; String companycode = "正泰集团股份有限公司";
String timespan = "1708908662738"; String timespan = "1708908662738";
String key = "ZhengTaiRoute"; String key = "ZhengTaiRoute";
String s = Digest.md5(sfno + syscode + billcode + companycode + key + timespan); String s = Digest.md5(sfno + syscode + billcode + companycode + key + timespan);