From 60dc853b57819f931516f6e9f27b11e2ea0e6ab3 Mon Sep 17 00:00:00 2001 From: lulz1 Date: Mon, 8 Jul 2024 15:44:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E8=A1=8C=E7=A8=8B?= =?UTF-8?q?=E8=A7=84=E5=88=92=E5=88=86=E9=A1=B5=E6=9F=A5=E8=AF=A2=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/out/LoginController.java | 2 +- .../application/queryies/OrderQuery.java | 12 +- .../chint/domain/aggregates/user/User.java | 2 + .../domain/repository/UserRepository.java | 5 +- .../service/auth/AuthenticateServiceImpl.java | 2 +- .../LYOrderRecordDomainService.java | 127 ++++++------ .../repository/AbstractGenericRepository.java | 185 ++++++++++++++---- .../repository/GenericCacheRepository.java | 58 ++++-- .../repository/JdbcGenericRepository.java | 5 - .../repository/RouteRepositoryImpl.java | 2 +- .../repository/UserRepositoryImpl.java | 84 ++++++-- .../repository/cache/CacheUserRepository.java | 10 + .../repository/jdbc/JdbcUserRepository.java | 5 + .../data_center/user/BatchUserWorker.java | 4 +- .../data_center/user/UserHttpRequestImpl.java | 6 +- src/test/java/com/chint/CTripTest.java | 2 +- src/test/java/com/chint/CacheTest.java | 22 +++ .../java/com/chint/RouteApplicationTests.java | 8 +- 18 files changed, 384 insertions(+), 157 deletions(-) create mode 100644 src/main/java/com/chint/infrastructure/repository/cache/CacheUserRepository.java diff --git a/src/main/java/com/chint/application/out/LoginController.java b/src/main/java/com/chint/application/out/LoginController.java index c42e7832..97b3a203 100644 --- a/src/main/java/com/chint/application/out/LoginController.java +++ b/src/main/java/com/chint/application/out/LoginController.java @@ -163,7 +163,7 @@ public class LoginController { CompletableFuture.runAsync(() -> { Command.of(UserLoginCommand.class).user(user).sendToQueue(); user.setSyncTime(LocalDateTime.now()); - userRepository.save(user); + userRepository.saveAndUpdateCache(user); }); } } diff --git a/src/main/java/com/chint/application/queryies/OrderQuery.java b/src/main/java/com/chint/application/queryies/OrderQuery.java index 279bd94a..2908aec5 100644 --- a/src/main/java/com/chint/application/queryies/OrderQuery.java +++ b/src/main/java/com/chint/application/queryies/OrderQuery.java @@ -36,6 +36,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -159,9 +160,12 @@ public class OrderQuery { int total = routeOrders.size(); routeApprovalDomainService.checkApprovalPermissions(routeOrders); -// Set employeeNoSet = routeOrders.stream().filter(it -> it.getApproveOrderNo() != null) -// .flatMap(it -> Stream.of(it.getUserId(), it.getApproveOrderNo().getCreator())) -// .collect(Collectors.toSet()); + Set employeeNoSet = routeOrders.stream().filter(it -> it.getApproveOrderNo() != null) + .flatMap(it -> Stream.of(it.getUserId(), it.getApproveOrderNo().getCreator())) + .collect(Collectors.toSet()); + Map userMap = userRepository.findByEmployeeNoIn(employeeNoSet) + .stream() + .collect(Collectors.toMap(User::getEmployeeNo, Function.identity())); List orders = routeOrders .stream() .sorted(statusComparator.thenComparing(RouteOrder::getUpdateTime).reversed()) @@ -171,7 +175,7 @@ public class OrderQuery { if (legDomainService.checkLocation(routeOrder.getLegItems())) { routeRepository.reloadRouteOrderInCache(routeOrder); } - User user = userRepository.findByUserEmployeeNo(routeOrder.getUserId()); + User user = userMap.get(routeOrder.getUserId()); return getRouteOrderPageRes(routeOrder, user); }) .toList(); diff --git a/src/main/java/com/chint/domain/aggregates/user/User.java b/src/main/java/com/chint/domain/aggregates/user/User.java index 34b3b542..8e833b4d 100644 --- a/src/main/java/com/chint/domain/aggregates/user/User.java +++ b/src/main/java/com/chint/domain/aggregates/user/User.java @@ -15,6 +15,7 @@ import com.chint.infrastructure.echo_framework.command.Command; import com.chint.infrastructure.util.BaseContext; import com.chint.infrastructure.util.StringCheck; 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.reflect.TypeToken; import lombok.AllArgsConstructor; @@ -57,6 +58,7 @@ public class User implements Serializable { private String gender; private String phoneNumber; private String password; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime syncTime; private Integer status; @Transient diff --git a/src/main/java/com/chint/domain/repository/UserRepository.java b/src/main/java/com/chint/domain/repository/UserRepository.java index 69d730f5..b8741e50 100644 --- a/src/main/java/com/chint/domain/repository/UserRepository.java +++ b/src/main/java/com/chint/domain/repository/UserRepository.java @@ -3,16 +3,17 @@ package com.chint.domain.repository; import com.chint.domain.aggregates.user.User; import java.util.List; +import java.util.Optional; import java.util.Set; public interface UserRepository { - User findById(Long id); + Optional findById(Long id); User findByUserEmployeeNo(String employeeNo); List findByEmployeeNoIn(Set employeeNoSet); - User save(User user); + User saveAndUpdateCache(User user); void saveAll(List userList); diff --git a/src/main/java/com/chint/domain/service/auth/AuthenticateServiceImpl.java b/src/main/java/com/chint/domain/service/auth/AuthenticateServiceImpl.java index dded8b59..5d696871 100644 --- a/src/main/java/com/chint/domain/service/auth/AuthenticateServiceImpl.java +++ b/src/main/java/com/chint/domain/service/auth/AuthenticateServiceImpl.java @@ -65,7 +65,7 @@ public class AuthenticateServiceImpl implements AuthenticateService { //如果数据库不存在该用户,需要通过sf信息进行查询并保存到数据库 newUser.setCompanyCode(userLoginParam.getCompanyCode()); httpRequest.loadUserInfo(newUser); - userRepository.save(newUser); + userRepository.saveAndUpdateCache(newUser); newUser.setUserLoginParam(userLoginParam); return getUserLoginResult(newUser); } diff --git a/src/main/java/com/chint/domain/service/order_record/LYOrderRecordDomainService.java b/src/main/java/com/chint/domain/service/order_record/LYOrderRecordDomainService.java index 582c0011..a6fd19a9 100644 --- a/src/main/java/com/chint/domain/service/order_record/LYOrderRecordDomainService.java +++ b/src/main/java/com/chint/domain/service/order_record/LYOrderRecordDomainService.java @@ -64,12 +64,10 @@ public class LYOrderRecordDomainService { @ListenTo(command = "LYOrderRecordGenerateCommand", order = 0) - @Transactional public void generateFlightRecord(LYOrderRecordGenerateCommand command) { int count = 0;//初始化变量 int pageSize = 100; // 假设每页大小为10 int LoopNum;//需要的循环数 - ArrayList recordsTotal = new ArrayList<>(); do { PageRequest pageResult = PageRequest.of(count, pageSize); Page lyOrderFlightRecordPage = jdbcLyOrderFlightRecord.findAllByStatusIsNull(pageResult); @@ -77,34 +75,31 @@ public class LYOrderRecordDomainService { LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 //数据 List lyOrderFlightRecordPageList = lyOrderFlightRecordPage.toList(); - recordsTotal.addAll(lyOrderFlightRecordPageList); + List routeOrderNoList = lyOrderFlightRecordPageList + .stream() + .map(LyOrderFlightRecord::getOutApplayOrderNo) + .distinct() + .toList(); + List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); + Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), + it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); + List orderFlightRecordList = lyOrderFlightRecordPageList + .stream() + .map(it -> lyOrderRecordExtensionFactory.createFlightOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) + .toList(); + orderDetailDomainService.saveFlightOrderRecordBatch(orderFlightRecordList); + jdbcLyOrderFlightRecord.updateStatusByNullStatus(); count++; } while (count < LoopNum); //修改数据,将状态为null的设置为1 - List routeOrderNoList = recordsTotal - .stream() - .map(LyOrderFlightRecord::getOutApplayOrderNo) - .distinct() - .toList(); - List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); - Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), - it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); - List orderFlightRecordList = recordsTotal - .stream() - .map(it -> lyOrderRecordExtensionFactory.createFlightOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) - .toList(); - orderDetailDomainService.saveFlightOrderRecordBatch(orderFlightRecordList); - jdbcLyOrderFlightRecord.updateStatusByNullStatus(); } @ListenTo(command = "LYOrderRecordGenerateCommand", order = 1) - @Transactional public void generateHotelRecord(LYOrderRecordGenerateCommand command) { int count = 0;//初始化变量 int pageSize = 100; // 假设每页大小为10 int LoopNum;//需要的循环数 - ArrayList recordsTotal = new ArrayList<>(); do { PageRequest pageResult = PageRequest.of(count, pageSize); Page lyOrderHotelRecordPage = jdbcLyOrderHotelRecord.findAllByStatusIsNull(pageResult); @@ -112,34 +107,32 @@ public class LYOrderRecordDomainService { LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 //数据 List lyOrderHotelRecordPageList = lyOrderHotelRecordPage.toList(); - recordsTotal.addAll(lyOrderHotelRecordPageList); + //修改数据,将状态为null的设置为1 + List routeOrderNoList = lyOrderHotelRecordPageList + .stream() + .map(LyOrderHotelRecord::getOutApplayOrderNo) + .distinct() + .toList(); + List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); + Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), + it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); + List orderHotelRecordList = lyOrderHotelRecordPageList + .stream() + .map(it -> lyOrderRecordExtensionFactory.createHotelOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) + .toList(); + orderDetailDomainService.saveHotelOrderRecordBatch(orderHotelRecordList); + jdbcLyOrderHotelRecord.updateStatusByNullStatus(); count++; } while (count < LoopNum); //修改数据,将状态为null的设置为1 - List routeOrderNoList = recordsTotal - .stream() - .map(LyOrderHotelRecord::getOutApplayOrderNo) - .distinct() - .toList(); - List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); - Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), - it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); - List orderHotelRecordList = recordsTotal - .stream() - .map(it -> lyOrderRecordExtensionFactory.createHotelOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) - .toList(); - orderDetailDomainService.saveHotelOrderRecordBatch(orderHotelRecordList); - jdbcLyOrderHotelRecord.updateStatusByNullStatus(); } @ListenTo(command = "LYOrderRecordGenerateCommand", order = 2) - @Transactional public void generateTrainRecord(LYOrderRecordGenerateCommand command) { int count = 0;//初始化变量 int pageSize = 100; // 假设每页大小为10 int LoopNum;//需要的循环数 - ArrayList recordsTotal = new ArrayList<>(); do { PageRequest pageResult = PageRequest.of(count, pageSize); Page lyOrderTrainRecordPage = jdbcLyOrderTrainRecord.findAllByStatusIsNull(pageResult); @@ -147,34 +140,32 @@ public class LYOrderRecordDomainService { LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 //数据 List lyOrderTrainRecordPageList = lyOrderTrainRecordPage.toList(); - recordsTotal.addAll(lyOrderTrainRecordPageList); + List routeOrderNoList = lyOrderTrainRecordPageList + .stream() + .map(LyOrderTrainRecord::getOutApplayOrderNo) + .distinct() + .toList(); + List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); + Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), + it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); + List orderTrainRecordList = lyOrderTrainRecordPageList + .stream() + .map(it -> lyOrderRecordExtensionFactory.createTrainOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) + .toList(); + orderDetailDomainService.saveTrainOrderRecordBatch(orderTrainRecordList); + jdbcLyOrderTrainRecord.updateStatusByNullStatus(); count++; } while (count < LoopNum); //修改数据,将状态为null的设置为1 - List routeOrderNoList = recordsTotal - .stream() - .map(LyOrderTrainRecord::getOutApplayOrderNo) - .distinct() - .toList(); - List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); - Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), - it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); - List orderTrainRecordList = recordsTotal - .stream() - .map(it -> lyOrderRecordExtensionFactory.createTrainOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) - .toList(); - orderDetailDomainService.saveTrainOrderRecordBatch(orderTrainRecordList); - jdbcLyOrderTrainRecord.updateStatusByNullStatus(); + } @ListenTo(command = "LYOrderRecordGenerateCommand", order = 3) - @Transactional public void generateCarRecord(LYOrderRecordGenerateCommand command) { int count = 0;//初始化变量 int pageSize = 100; // 假设每页大小为10 int LoopNum;//需要的循环数 - ArrayList recordsTotal = new ArrayList<>(); do { PageRequest pageResult = PageRequest.of(count, pageSize); Page lyOrderCarRecordPage = jdbcLyOrderCarRecord.findAllByStatusIsNull(pageResult); @@ -182,24 +173,24 @@ public class LYOrderRecordDomainService { LoopNum = (int) Math.ceil((double) totalElements / pageSize); // 计算总页数并向上取整 //数据 List lyOrderCarRecordPageList = lyOrderCarRecordPage.toList(); - recordsTotal.addAll(lyOrderCarRecordPageList); + //修改数据,将状态为null的设置为1 + List routeOrderNoList = lyOrderCarRecordPageList + .stream() + .map(LyOrderCarRecord::getOutApplayOrderNo) + .distinct() + .toList(); + List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); + Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), + it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); + List orderCarRecordList = lyOrderCarRecordPageList + .stream() + .map(it -> lyOrderRecordExtensionFactory.createCarOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) + .toList(); + orderDetailDomainService.saveCarOrderRecordBatch(orderCarRecordList); + jdbcLyOrderCarRecord.updateStatusByNullStatus(); count++; } while (count < LoopNum); //修改数据,将状态为null的设置为1 - List routeOrderNoList = recordsTotal - .stream() - .map(LyOrderCarRecord::getOutApplayOrderNo) - .distinct() - .toList(); - List routeOrderList = routeRequestDomainService.getRouteOrder(routeOrderNoList); - Map> collect = routeOrderNoList.parallelStream().collect(Collectors.toMap(Function.identity(), - it -> routeOrderList.stream().filter(routeOrder ->routeOrder != null && routeOrder.checkIfMine(it)).findFirst())); - List orderCarRecordList = recordsTotal - .stream() - .map(it -> lyOrderRecordExtensionFactory.createCarOrderRecord(it, collect.get(it.getOutApplayOrderNo()))) - .toList(); - orderDetailDomainService.saveCarOrderRecordBatch(orderCarRecordList); - jdbcLyOrderCarRecord.updateStatusByNullStatus(); } diff --git a/src/main/java/com/chint/infrastructure/echo_framework/repository/AbstractGenericRepository.java b/src/main/java/com/chint/infrastructure/echo_framework/repository/AbstractGenericRepository.java index af095c0d..12752f4f 100644 --- a/src/main/java/com/chint/infrastructure/echo_framework/repository/AbstractGenericRepository.java +++ b/src/main/java/com/chint/infrastructure/echo_framework/repository/AbstractGenericRepository.java @@ -1,66 +1,183 @@ package com.chint.infrastructure.echo_framework.repository; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; public abstract class AbstractGenericRepository { protected final GenericCacheRepository cacheRepository; - protected final JdbcGenericRepository jdbcRepository; protected final String cachePrefix; + protected final Map, List>> fieldQueryMap = new HashMap<>(); - protected AbstractGenericRepository(GenericCacheRepository cacheRepository, - JdbcGenericRepository jdbcRepository, - String cachePrefix) { + + public AbstractGenericRepository addFieldQueryMap(String fieldPrefix, + Function, List> fieldQuery) { + fieldQueryMap.put(fieldPrefix, fieldQuery); + return this; + } + + protected AbstractGenericRepository(GenericCacheRepository cacheRepository) { this.cacheRepository = cacheRepository; - this.jdbcRepository = jdbcRepository; - this.cachePrefix = cachePrefix; + this.cachePrefix = getPrefix(); } - public T save(T entity) { - T savedEntity = jdbcRepository.save(entity); - updateCache(savedEntity); - return savedEntity; + public T saveAndUpdateCache(T entity) { + save(entity); + updateCache(entity); + return entity; } - public T findById(ID id) { - T entity = cacheRepository.findFromCache(cachePrefix, id); - if (entity == null) { - Optional optionalEntity = jdbcRepository.findById(id); + public abstract T save(T entity); + + public Optional findById(ID id, Function> function) { + Optional entity = Optional.ofNullable(cacheRepository.findFromCache(cachePrefix, id)); + if (entity.isEmpty()) { + Optional optionalEntity = function.apply(id); if (optionalEntity.isPresent()) { - entity = optionalEntity.get(); - T finalEntity = entity; + T finalEntity = optionalEntity.get(); CompletableFuture.runAsync(() -> updateCache(finalEntity)); } + return optionalEntity; } return entity; } - public T findByField(Function fieldGetter, String fieldPrefix) { - ID id = cacheRepository.findIdFromCache(fieldPrefix, fieldGetter.toString()); - if (id == null) { - T entity = findByFieldFromDatabase(fieldGetter); - if (entity != null) { - CompletableFuture.runAsync(() -> updateCache(entity)); - } - return entity; - } - return findById(id); + + private Optional findEntity(String fieldPrefix, String fieldValue) { + return fieldQueryMap.get(fieldPrefix).apply(Set.of(fieldValue)).stream().findFirst(); } + private Optional findByFieldCommon(String fieldPrefix, + String fieldValue, Supplier idSupplier, + Supplier> entitySupplier, + Function> function) { + ID id = idSupplier.get(); + if (id == null) { + Optional 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 Optional findByField(String fieldPrefix, String fieldValue) { + return findByField(fieldPrefix, fieldValue, this::findByIdFromDB); + } + +// public Optional findByField(String fieldPrefix, Function fieldGetter, Function> function) { +// return findByFieldCommon( +// fieldPrefix, fieldGetter.apply() +// () -> cacheRepository.findIdFromCache(cachePrefix, fieldPrefix, fieldGetter.toString()), +// () -> findEntity(fieldPrefix, fieldGetter.toString()), (id) -> findById(id, function); +// ); +// } + + public Optional findByField(String fieldPrefix, String fieldValue, Function> function) { + return findByFieldCommon( + fieldPrefix, fieldValue, + () -> cacheRepository.findIdFromCache(cachePrefix, fieldPrefix, fieldValue), + () -> findEntity(fieldPrefix, fieldValue), + (id) -> findById(id, function) + ); + } + + public List findByIdsIn(Set ids) { + // Step 1: Get data from cache + List inCacheList = cacheRepository.findBatchByIds(cachePrefix, ids); + + // Step 2: Identify cached IDs and missing IDs + List cachedIds = inCacheList.stream() + .filter(Objects::nonNull) + .map(this::getPrimaryKeys) + .map(Object::toString) + .map(id -> (ID) id) + .toList(); + List 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 fetchedList = findByIdsInFromDB(new HashSet<>(missingIds)); + inCacheList.addAll(fetchedList); + CompletableFuture.runAsync(() -> fetchedList.forEach(this::updateCache)); + } + + // Step 4: Return the complete list + return inCacheList; + } + + public List findByFieldsIn(String fieldPrefix, + Set fieldValues, + Function fieldGetter, + Function, List> fieldQueryMethod) { + + // Step 1: Get IDs from cache + Set ids = new HashSet<>(cacheRepository.findIdsFromCache(cachePrefix, fieldPrefix, fieldValues)); + + // Step 2: Get data from cache using IDs + List inCacheList = cacheRepository.findBatchByIds(cachePrefix, ids); + + // Step 3: Identify cached IDs and missing IDs + List cachedFields = inCacheList.stream() + .filter(Objects::nonNull) + .map(fieldGetter) + .toList(); + + Set 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 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 findByFieldsIn(String fieldPrefix, + Set fieldValues, + Function fieldGetter) { + return findByFieldsIn(fieldPrefix, fieldValues, fieldGetter, fieldQueryMap.get(fieldPrefix)); + } + + protected abstract Optional findByIdFromDB(ID id); + + protected abstract List findByIdsInFromDB(Set ids); + + //通过主键实现该方法 + protected abstract ID getPrimaryKeys(T entity); + protected abstract String getPrefix(); - protected abstract T findByFieldFromDatabase(V fieldValue); + public void updateCache(T entity) { + beforeUpdateCache(); + cacheRepository.cacheEvict(cachePrefix, getPrimaryKeys(entity)); + cacheRepository.cache(cachePrefix, getPrimaryKeys(entity), entity); + } - protected abstract List findByFieldInFromDatabase(List fieldValueList); - - protected abstract void updateCache(T entity); + protected abstract String beforeUpdateCache(); protected void updateFieldCache(String fieldName, String fieldValue, ID id) { - cacheRepository.cacheEvictFieldToId(fieldName, fieldValue); - cacheRepository.cacheFieldToId(fieldName, fieldValue, id); + cacheRepository.cacheEvictFieldToId(cachePrefix, fieldName, fieldValue); + cacheRepository.cacheFieldToId(cachePrefix, fieldName, fieldValue, id); } protected String getFieldPrefix(String fieldName) { diff --git a/src/main/java/com/chint/infrastructure/echo_framework/repository/GenericCacheRepository.java b/src/main/java/com/chint/infrastructure/echo_framework/repository/GenericCacheRepository.java index fcb368da..b2f9f59a 100644 --- a/src/main/java/com/chint/infrastructure/echo_framework/repository/GenericCacheRepository.java +++ b/src/main/java/com/chint/infrastructure/echo_framework/repository/GenericCacheRepository.java @@ -1,10 +1,11 @@ package com.chint.infrastructure.echo_framework.repository; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; +import java.time.Duration; import java.util.List; +import java.util.Map; +import java.util.Set; public class GenericCacheRepository { @@ -13,6 +14,7 @@ public class GenericCacheRepository { private final RedisTemplate redisTemplateId; private final Class entityType; private final Class idType; + private final Duration cacheExpiration; // 添加缓存失效时间 public GenericCacheRepository(RedisTemplate redisTemplate, RedisTemplate redisTemplateId, @@ -22,15 +24,20 @@ public class GenericCacheRepository { this.redisTemplateId = redisTemplateId; this.entityType = entityType; this.idType = idType; + this.cacheExpiration = Duration.ofHours(6L); } private String getKey(String prefix, Object 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) { String key = getKey(prefix, id); - redisTemplate.opsForValue().set(key, entity); + redisTemplate.opsForValue().set(key, entity, cacheExpiration); return entity; } @@ -44,29 +51,48 @@ public class GenericCacheRepository { return redisTemplate.opsForValue().get(key); } - public List cacheBatchByIds(String prefix, List ids) { + public List findBatchByIds(String prefix, Set ids) { List keys = ids.stream().map(id -> getKey(prefix, id)).toList(); return redisTemplate.opsForValue().multiGet(keys); } - public ID cacheFieldToId(String fieldPrefix, String fieldValue, ID id) { - String key = getKey(fieldPrefix, fieldValue); - redisTemplateId.opsForValue().set(key, id); + public ID cacheFieldToId(String prefix, String fieldPrefix, + String fieldValue, ID id) { + String key = getKey(prefix, fieldPrefix, fieldValue); + redisTemplateId.opsForValue().set(key, id, cacheExpiration); return id; } - public ID findIdFromCache(String fieldPrefix, String fieldValue) { - String key = getKey(fieldPrefix, fieldValue); + public void cacheEvictFieldToId(String prefix, String fieldPrefix, String fieldValue) { + String key = getKey(prefix, fieldPrefix, fieldValue); + redisTemplateId.delete(key); + } + + public void cacheFieldsToIdsBatch(String prefix, String fieldPrefix, + Map 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 fieldValues) { + List 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); } - public List findIdsFromCache(String fieldPrefix, List fieldValueList) { - List keys = fieldValueList.stream().map(fieldValue -> getKey(fieldPrefix, fieldValue)).toList(); + public List findIdsFromCache(String prefix, String fieldPrefix, + Set fieldValueList) { + List keys = fieldValueList.stream().map(fieldValue -> getKey(prefix, fieldPrefix, fieldValue)) + .toList(); return redisTemplateId.opsForValue().multiGet(keys); } - - public void cacheEvictFieldToId(String fieldPrefix, String fieldValue) { - String key = getKey(fieldPrefix, fieldValue); - redisTemplateId.delete(key); - } } \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/echo_framework/repository/JdbcGenericRepository.java b/src/main/java/com/chint/infrastructure/echo_framework/repository/JdbcGenericRepository.java index 1303f49c..6096ff70 100644 --- a/src/main/java/com/chint/infrastructure/echo_framework/repository/JdbcGenericRepository.java +++ b/src/main/java/com/chint/infrastructure/echo_framework/repository/JdbcGenericRepository.java @@ -8,9 +8,4 @@ import java.util.Optional; @Repository public interface JdbcGenericRepository extends CrudRepository { - Optional findById(ID id); - - List findAll(); - - List findByIdIn(List ids); } \ No newline at end of file diff --git a/src/main/java/com/chint/infrastructure/repository/RouteRepositoryImpl.java b/src/main/java/com/chint/infrastructure/repository/RouteRepositoryImpl.java index 857089a1..a1c1f869 100644 --- a/src/main/java/com/chint/infrastructure/repository/RouteRepositoryImpl.java +++ b/src/main/java/com/chint/infrastructure/repository/RouteRepositoryImpl.java @@ -230,7 +230,7 @@ public class RouteRepositoryImpl implements RouteRepository { routeOrder.setUpdateTime(LocalDateTime.now()); } 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; } } diff --git a/src/main/java/com/chint/infrastructure/repository/UserRepositoryImpl.java b/src/main/java/com/chint/infrastructure/repository/UserRepositoryImpl.java index c8e519d9..ec799e4c 100644 --- a/src/main/java/com/chint/infrastructure/repository/UserRepositoryImpl.java +++ b/src/main/java/com/chint/infrastructure/repository/UserRepositoryImpl.java @@ -1,51 +1,105 @@ package com.chint.infrastructure.repository; import com.chint.domain.aggregates.user.User; +import com.chint.domain.exceptions.CommandException; 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.interfaces.rest.base.PostRequest; +import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Repository; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.Set; @Repository -public class UserRepositoryImpl implements UserRepository { +public class UserRepositoryImpl extends AbstractGenericRepository implements UserRepository { @Autowired private JdbcUserRepository jdbcUserRepository; - @Override - public User findById(Long id) { - return null; + @Autowired + private CacheUserRepository cacheUserRepository; + + @Autowired + private RedisTemplate redisTemplate; + @Autowired + private RedisTemplate redisTemplateId; + @Autowired + private PostRequest postRequest; + + @Autowired + public UserRepositoryImpl(JdbcUserRepository jdbcUserRepository, + CacheUserRepository cacheUserRepository, + RedisTemplate redisTemplate, + RedisTemplate 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 findById(Long id) { + return findById(id, (userId) -> jdbcUserRepository.findById(userId)); + } + + @Override + protected List findByIdsInFromDB(Set 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 public User findByUserEmployeeNo(String employeeNo) { - return jdbcUserRepository.findByEmployeeNo(employeeNo); + return this.findByField("EmployeeNo", employeeNo) + .orElseThrow(() -> new CommandException("Employee Not Found")); } @Override public List findByEmployeeNoIn(Set employeeNoSet) { - return List.of(); + return this.findByFieldsIn("EmployeeNo", employeeNoSet, + User::getEmployeeNo, + (set) -> jdbcUserRepository.findByEmployeeNoIn(employeeNoSet)); } - - @CacheEvict(value = "UserEmployeeNoCache", key = "#user.employeeNo") @Override public User save(User user) { - User byEmployeeNo = jdbcUserRepository.findByEmployeeNo(user.getEmployeeNo()); - if (byEmployeeNo != null) { - user.setUserId(byEmployeeNo.getUserId()); - } return jdbcUserRepository.save(user); } + @Override + protected Optional findByIdFromDB(Long aLong) { + return jdbcUserRepository.findById(aLong); + } + + @Override public void saveAll(List userList) { jdbcUserRepository.saveAll(userList); diff --git a/src/main/java/com/chint/infrastructure/repository/cache/CacheUserRepository.java b/src/main/java/com/chint/infrastructure/repository/cache/CacheUserRepository.java new file mode 100644 index 00000000..7ff29967 --- /dev/null +++ b/src/main/java/com/chint/infrastructure/repository/cache/CacheUserRepository.java @@ -0,0 +1,10 @@ +package com.chint.infrastructure.repository.cache; + +import org.springframework.stereotype.Repository; + +@Repository +public class CacheUserRepository { + + + +} diff --git a/src/main/java/com/chint/infrastructure/repository/jdbc/JdbcUserRepository.java b/src/main/java/com/chint/infrastructure/repository/jdbc/JdbcUserRepository.java index 40a86a59..0c1e8218 100644 --- a/src/main/java/com/chint/infrastructure/repository/jdbc/JdbcUserRepository.java +++ b/src/main/java/com/chint/infrastructure/repository/jdbc/JdbcUserRepository.java @@ -6,12 +6,17 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; +import java.util.Collection; import java.util.List; @Repository public interface JdbcUserRepository extends CrudRepository { User findByEmployeeNo(String employeeNo); + List findByEmployeeNoIn(Collection employeeNo); + + List findByUserIdIn(Collection userId); + List findByStatus(Integer status); List findByStatusIsNull(); diff --git a/src/main/java/com/chint/interfaces/rest/data_center/user/BatchUserWorker.java b/src/main/java/com/chint/interfaces/rest/data_center/user/BatchUserWorker.java index 5d859830..686681a4 100644 --- a/src/main/java/com/chint/interfaces/rest/data_center/user/BatchUserWorker.java +++ b/src/main/java/com/chint/interfaces/rest/data_center/user/BatchUserWorker.java @@ -111,7 +111,7 @@ public class BatchUserWorker { } else { user.setStatus(1); } - userRepository.save(user); + userRepository.saveAndUpdateCache(user); } } @@ -228,7 +228,7 @@ public class BatchUserWorker { cTripUserSaveRequest.saveUserToCTrip(user); // 发送保存用户同步时间 user.setSyncTime(LocalDateTime.now()); - userRepository.save(user); + userRepository.saveAndUpdateCache(user); } diff --git a/src/main/java/com/chint/interfaces/rest/data_center/user/UserHttpRequestImpl.java b/src/main/java/com/chint/interfaces/rest/data_center/user/UserHttpRequestImpl.java index 76b9e1b9..1c613ad2 100644 --- a/src/main/java/com/chint/interfaces/rest/data_center/user/UserHttpRequestImpl.java +++ b/src/main/java/com/chint/interfaces/rest/data_center/user/UserHttpRequestImpl.java @@ -187,7 +187,7 @@ public class UserHttpRequestImpl implements UserHttpRequest { .ifPresent(it -> { User byUserEmployeeNo = userRepository.findByUserEmployeeNo(user.getEmployeeNo()); if (byUserEmployeeNo == null) { - userRepository.save( + userRepository.saveAndUpdateCache( getDataFromUserSFData(user, it) ); } @@ -224,7 +224,7 @@ public class UserHttpRequestImpl implements UserHttpRequest { getDataFromUserSFData(user, userDataDTOList.get(0)); } - return userRepository.save(user); + return userRepository.saveAndUpdateCache(user); } public String belongDeport(String employeeNo, String accountCompanyName) { @@ -248,7 +248,7 @@ public class UserHttpRequestImpl implements UserHttpRequest { List userDepartmentInfos = userDepartmentInfoList.stream().distinct().toList(); if (userDepartmentInfos.size() < userDepartmentInfoList.size()) { user.setUserDepartmentInfoList(userDepartmentInfos); - userRepository.save(user); + userRepository.saveAndUpdateCache(user); } } diff --git a/src/test/java/com/chint/CTripTest.java b/src/test/java/com/chint/CTripTest.java index 766439cf..5ec40f20 100644 --- a/src/test/java/com/chint/CTripTest.java +++ b/src/test/java/com/chint/CTripTest.java @@ -250,7 +250,7 @@ public class CTripTest { @Test void search() { BaseContext.setCurrentUser(user); - SearchOrderResponse response = orderSearchRequest.searchOrderResponseByOrderId("32055893290"); + SearchOrderResponse response = orderSearchRequest.searchOrderResponseByOrderId("33303376379"); System.out.println(response); } diff --git a/src/test/java/com/chint/CacheTest.java b/src/test/java/com/chint/CacheTest.java index 5ab55c76..e7df3fa5 100644 --- a/src/test/java/com/chint/CacheTest.java +++ b/src/test/java/com/chint/CacheTest.java @@ -2,6 +2,8 @@ package com.chint; 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.RouteCacheService; 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 java.util.List; +import java.util.Set; @SpringBootTest public class CacheTest { @@ -25,6 +28,11 @@ public class CacheTest { @Autowired private RouteCacheManage routeCacheManage; + @Autowired + private UserRepository userRepository; + + private Gson gson = new Gson(); + // @Test public void getAllRouteOrderById(){ List keys = List.of("RouteOrders::900","RouteOrders::918"); @@ -51,4 +59,18 @@ public class CacheTest { public void cancelCache(){ 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)); + } } diff --git a/src/test/java/com/chint/RouteApplicationTests.java b/src/test/java/com/chint/RouteApplicationTests.java index 471e8ece..a0b8d092 100644 --- a/src/test/java/com/chint/RouteApplicationTests.java +++ b/src/test/java/com/chint/RouteApplicationTests.java @@ -324,10 +324,10 @@ class RouteApplicationTests { @Test void loginSignProd() { - String sfno = "210506025"; - String syscode = "ANFSSC"; - String billcode = "CLS24062700018"; - String companycode = "正泰安能数字能源(浙江)股份有限公司"; + String sfno = "231026051"; + String syscode = "FSSC"; + String billcode = "CLSQ240225000099"; + String companycode = "正泰集团股份有限公司"; String timespan = "1708908662738"; String key = "ZhengTaiRoute"; String s = Digest.md5(sfno + syscode + billcode + companycode + key + timespan);