Last active
September 25, 2023 14:05
-
-
Save GordPavel/bba52936848cd97df5952837b7fa0875 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // package my.code.cache.dao | |
| public class CacheEntity { | |
| String id; | |
| String jsonData; | |
| } | |
| public interface CacheEntityRepository { | |
| Optional<CacheEntity> findById(String id); | |
| CacheEntity save(CacheEntity entity); | |
| } | |
| // package my.code.cache.dao.jpa | |
| interface JpaCacheEntityRepository extends JpaRepository<CacheEntity, String>, CacheEntityRepository {} | |
| // package my.code.cache | |
| public class Cache<T> { | |
| String id; | |
| T data; | |
| private Cache(String id, T data) { | |
| this.id = id; | |
| this.data = data; | |
| } | |
| public String getId() { | |
| return id; | |
| } | |
| public T getData() { | |
| return data; | |
| } | |
| } | |
| public abstract class CacheService<T> { | |
| protected abstract Optional<Cache<T>> fetchFromCache(String id); | |
| protected abstract void putToCache(Cache<T> cache); | |
| } | |
| public class CacheServiceMapper { | |
| private final ObjectMapper objectMapper; | |
| public CacheServiceMapper(ObjectMapper objectMapper) { | |
| this.objectMapper = objectMapper; | |
| } | |
| <T> Cache<T> fromEntity(CacheEntity entity, Class<T> dataType) { | |
| try { | |
| return new Cache<>(entity.id, objectMapper.readValue(entity.jsonData, dataType)); | |
| } catch (JsonProcessingException e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| CacheEntity toEntity(Cache<?> cache) { | |
| final var cacheEntity = new CacheEntity(); | |
| cacheEntity.id = cache.id; | |
| try { | |
| cacheEntity.jsonData = objectMapper.writeValueAsString(cache.data); | |
| } catch (JsonProcessingException e) { | |
| throw new RuntimeException(e); | |
| } | |
| return cacheEntity; | |
| } | |
| } | |
| public abstract class AbstractCacheService<T, K> extends CacheService<T> { | |
| private final CacheEntityRepository cacheEntityRepository; | |
| private final CacheServiceMapper cacheServiceMapper; | |
| AbstractCacheService( | |
| CacheEntityRepository jpaCacheEntityRepository, | |
| CacheServiceMapper cacheServiceMapper | |
| ) { | |
| this.cacheEntityRepository = jpaCacheEntityRepository; | |
| this.cacheServiceMapper = cacheServiceMapper; | |
| } | |
| @Override | |
| protected Optional<Cache<T>> fetchFromCache(String id) { | |
| return cacheEntityRepository | |
| .findById(id) | |
| .map(entity -> cacheServiceMapper.fromEntity(entity, dataClass())); | |
| } | |
| @Override | |
| protected void putToCache(Cache<T> cache) { | |
| cacheEntityRepository.save(cacheServiceMapper.toEntity(cache)); | |
| } | |
| protected abstract Class<T> dataClass(); | |
| } | |
| // package my.code.party | |
| class Party { | |
| UUID id; | |
| public UUID getId() { | |
| return id; | |
| } | |
| } | |
| // package my.code.party.cache | |
| abstract class PartyCache extends AbstractCacheService<Party, UUID> { | |
| PartyCache(CacheEntityRepository jpaCacheEntityRepository, CacheServiceMapper cacheServiceMapper) { | |
| super(jpaCacheEntityRepository, cacheServiceMapper); | |
| } | |
| @Override | |
| protected Class<Party> dataClass() { | |
| return Party.class; | |
| } | |
| public Optional<Party> fetchPartyFromCache(UUID id) { | |
| return super.fetchFromCache(id.toString()).map(Cache::getData); | |
| } | |
| public void putPartyToCache(Party party) { | |
| super.putToCache(new Cache<>(party.getId().toString(), party)); | |
| } | |
| } | |
| class PostgresPartyCache extends PartyCache { | |
| PostgresPartyCache(JpaCacheEntityRepository jpaCacheEntityRepository, CacheServiceMapper cacheServiceMapper) { | |
| super(jpaCacheEntityRepository, cacheServiceMapper); | |
| } | |
| } | |
| // package my.code.party.dao.jpa | |
| static class PartyEntity { | |
| UUID id; | |
| } | |
| interface JpaPartyEntityRepository extends JpaRepository<PartyEntity, UUID> {} | |
| interface PartyDaoMapper { | |
| Party fromEntity(PartyEntity party); | |
| PartyEntity toEntity(Party party); | |
| } | |
| // package my.code.party.dao | |
| class PartyDao { | |
| private final JpaPartyEntityRepository partyEntityRepository; | |
| private final PartyCache partyCache; | |
| private final PartyDaoMapper partyDaoMapper; | |
| PartyDao( | |
| JpaPartyEntityRepository partyEntityRepository, | |
| PartyCache partyCache, | |
| PartyDaoMapper partyDaoMapper | |
| ) { | |
| this.partyEntityRepository = partyEntityRepository; | |
| this.partyCache = partyCache; | |
| this.partyDaoMapper = partyDaoMapper; | |
| } | |
| Optional<Party> findPartyById(UUID id) { | |
| final var cachedParty = partyCache.fetchPartyFromCache(id); | |
| if (cachedParty.isPresent()) { | |
| return cachedParty; | |
| } | |
| final var party = partyEntityRepository.findById(id).map(partyDaoMapper::fromEntity); | |
| if (party.isPresent()) { | |
| partyCache.putPartyToCache(party.get()); | |
| return party; | |
| } | |
| return Optional.empty(); | |
| } | |
| void saveParty(Party party) { | |
| partyCache.putPartyToCache(party); | |
| partyEntityRepository.save(partyDaoMapper.toEntity(party)); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment