avataromgzui

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

1837

Abstract

id spotless.</p><p id="036a">My mum liked her home to be comfortable. She believed in clean, but ‘lived in.’ She wasn’t ever 100% tidy, she was <i>comfortably tidy. </i>Some days I would come home from school and every room in the house would be a little messy. However, if my mum had spent all day tidying up, she’d never have had a life.</p><p id="8f57">When my own children were young, my home was never ‘spotless’, and some professionals often complained that<b> I wasn’t tidy or clean enough.</b></p><p id="6e46">Bringing up six children was really hard, I did not have time to clean and tidy all day! Besides,</p><p id="3d1b" type="7">being too tidy and stressing yourself out over it in front of children teaches them that being messy is wrong!</p><p id="626e">If children grow up believing that cleaning is the only way to live, then they will grow up anxious about every little mess they make.</p><p id="a244" type="7">Parents should feel free to spend more time with their children because children need them more than housework needs them.</p><p id="04c5">My children are grown up today, but I still don’t do 100% tidy. I have laundry in my lounge to put away, and baskets of dirty clothes to wash, and everything is out of place,</p><p id="8f70"><b>But, I will clean it up in my own time.</b></p><p id="935a">We<i> </i>need to drop the concept of spotless because it causes people more stress than it is worth. Of course, we do need to clean and tidy our homes every now and then, in order to create a healthy home.</p><p id="9681">However, being too clean and tidy can be unhealthy; and in today’s world, do you really want to spend the rest of your life absorbed in chores?</p><p id="ac8b"><b>Life is for living, so please go away if you want spotless. You won’t get it at my house!</b></p><p id="a3e5">You might like to re

Options

ad the following:</p><div id="f87f" class="link-block"> <a href="https://readmedium.com/a-memory-never-forgotten-d92b5dfb2afa"> <div> <div> <h2>A Memory Never Forgotten.</h2> <div><h3>Writing: In The Beginning</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*jGTV-_KNxfyyAbfq)"></div> </div> </div> </a> </div><div id="d4cf" class="link-block"> <a href="https://readmedium.com/swing-swing-swing-40ef21118106"> <div> <div> <h2>Swing! Swing! Swing!</h2> <div><h3>About a little boy who had an obsession with the swings, yet left some golden moments in my heart to treasure forever.</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*d_Y5f3Tn1IJuAAoN)"></div> </div> </div> </a> </div><div id="d68e" class="link-block"> <a href="https://readmedium.com/do-you-always-feel-like-a-packhorse-after-a-holiday-cbb1e481b853"> <div> <div> <h2>Do You Always Feel Like a Packhorse After a Holiday?</h2> <div><h3>I always end up with more bags than I went with!</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*8TtnVjKGWer24Tx4)"></div> </div> </div> </a> </div></article></body>

Drop RedisTemplate and Use JPA Repository Instead

Photo by Manja Vitolic on Unsplash

I have worked for many years and have used both methods, but it still depends on the usage scenario to decide which one to use. Overall, JPA Repository will be more convenient to use.

RedisTemplate

RedisTemplate is the best way to understand. We first define a POJO class, a very simple BOOK class, with three fields: id, name, and author. Then a RedisTemplate Bean, and then define a Service class that uses this RedisTemplate.

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Book implements Serializable {
    private Long id;
    private String name;
​
    private String author;
}

@Bean
public RedisTemplate<String, Book> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Book> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}
public Optional<Book> findOneBook(String name) {
    HashOperations<String, String, Book> hashOperations = redisTemplate.opsForHash();
    if (redisTemplate.hasKey(CACHE) && hashOperations.hasKey(CACHE, name)) {
        log.info("Get book {} from Redis.", name);
        return Optional.of(hashOperations.get(CACHE, name));
    }
​
    Optional<Book> book = bookRepository.getBook(name);
    log.info("Book Found: {}", book);
    if (book.isPresent()) {
        log.info("Put book {} to Redis.", name);
        hashOperations.put(CACHE, name, book.get());
        redisTemplate.expire(CACHE, 10, TimeUnit.MINUTES);
    }
    return book;
}

Use Hash to store this Book information. In the above method, check whether the title of the book exists in Redis. If it exists, it will return directly. It will go to the persistent storage to find it if it does not exist. If it is found, it will write it to Redis through Template. This is a common practice for caching. It feels very convenient to use. For the sake of simplicity, we did not use persistent storage here, so we hard-coded a few pieces of data.

@Repository
public class BookRepository {
    Map<String, Book> bookMap = new HashMap<>();
    public BookRepository(){
        bookMap.put("apache kafka", Book.builder()
                .name("apache kafka").id(1L).author("zhangsan")
                .build());
        bookMap.put("python", Book.builder()
                .name("python").id(2L).author("lisi")
                .build());
    }
​
    public Optional<Book> getBook(String name){
        if(bookMap.containsKey(name)){
            return Optional.of(bookMap.get(name));
        }
        else{
            return Optional.empty();
        }
    }
}

Call bookService.findOneBook(“python”) and bookService.findOneBook(“apache kafka”) to write data into the cache

127.0.0.1:6379> keys *
1) "\xac\xed\x00\x05t\x00\x04book"
127.0.0.1:6379> type "\xac\xed\x00\x05t\x00\x04book"
hash
127.0.0.1:6379> hgetall "\xac\xed\x00\x05t\x00\x04book"
1) "\xac\xed\x00\x05t\x00\x06python"
2) "\xac\xed\x00\x05sr\x00&com.ken.redistemplatesample.model.Book=\x19\x96\xfb\x7f\x7f\xda\xbe\x02\x00\x03L\x00\x06authort\x00\x12Ljava/lang/String;L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\x04nameq\x00~\x00\x01xpt\x00\x04lisisr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x02t\x00\x06python"
3) "\xac\xed\x00\x05t\x00\x0capache kafka"
4) "\xac\xed\x00\x05sr\x00&com.ken.redistemplatesample.model.Book=\x19\x96\xfb\x7f\x7f\xda\xbe\x02\x00\x03L\x00\x06authort\x00\x12Ljava/lang/String;L\x00\x02idt\x00\x10Ljava/lang/Long;L\x00\x04nameq\x00~\x00\x01xpt\x00\bzhangsansr\x00\x0ejava.lang.Long;\x8b\xe4\x90\xcc\x8f#\xdf\x02\x00\x01J\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00\x00\x00\x00\x01t\x00\x0capache kafka"

It can be seen that the data is stored in a Hash table whose key is “\xac\xed\x00\x05t\x00\x04book”, and there are two records in the Hash. Did you find a problem? That is, the key is not the “book” key we imagined, but a string of hexadecimal codes.

This is because RedisTemplate uses the default JdkSerializationRedisSerializer to serialize our key and value. If everyone uses the Java language That’s no problem. If someone writes in Java and someone reads in another language, there will be a problem, just like when I used the hgetall “book” at the beginning, I couldn’t get the data. RedisTemplate also provides StringRedisTemplate to facilitate the use of String to serialize the data in redis

@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
{
    StringRedisTemplate template = new StringRedisTemplate();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}
public Optional<String> getBookString(String name){
    HashOperations<String, String, String> hashOperations = stringRedisTemplate.opsForHash();
    if (stringRedisTemplate.hasKey(STRINGCACHE) && hashOperations.hasKey(STRINGCACHE, name)) {
        log.info("Get book {} from Redis.", name);
        return Optional.of(hashOperations.get(STRINGCACHE, name));
    }
​
    Optional<Book> book = bookRepository.getBook(name);
    log.info("Book Found: {}", book);
    if (book.isPresent()) {
        log.info("Put book {} to Redis.", name);
        hashOperations.put(STRINGCACHE, name, book.get().getAuthor());
        stringRedisTemplate.expire(STRINGCACHE, 10, TimeUnit.MINUTES);
        return Optional.of(book.get().getAuthor());
    }
    return Optional.empty();
}
127.0.0.1:6379> keys *
1) "string_book"
127.0.0.1:6379> hgetall string_book
1) "python"
2) "lisi"
3) "apache kafka"
4) "zhangsan"

JPA Repository

When using JPA Repository to access DataBase, operations such as adding, deleting, modifying, and checking can be easily realized. It is to define an interface without writing code. Spring will help us complete most of the work, so is it possible to access Redis? how about this? The answer is yes, let’s look at the code First we still define a POJO.

@RedisHash(value = "cache-book", timeToLive = 600)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CacheBook implements Serializable {
​
    @Id
    private Long userId;
​
    @Indexed
    private String name;
​
    private String author;
}

The difference between this class and the class above our template is that we added two annotations, @RedisHash(value = “cache-book”, timeToLive = 600) at the beginning of the class, and @Id and @Indexed definition on the field A Repository interface.

Then define a service like the template in the above example. If there is one in the cache, get it from the cache. If not, find it in the persistent storage and write it into the cache.

public interface CacheBookRepository extends CrudRepository<CacheBook, Long> {
    Optional<CacheBook> findOneByName(String name);
}
@Slf4j
@Service
public class BookService {
    private static final String CACHE = "repository-book";
    @Autowired
    private CacheBookRepository cacheRepository;
​
    @Autowired
    private BookRepository bookRepository;
​
    public Optional<CacheBook> findOneBook(String name) {
        Optional<CacheBook> optionalCacheBook = cacheRepository.findOneByName(name);
        if(!optionalCacheBook.isPresent())
        {
            Optional<CacheBook> book = bookRepository.getBook(name);
            log.info("Book Found: {}", book);
            if (book.isPresent()) {
                log.info("Put book {} to Redis.", name);
                cacheRepository.save(book.get());
            }
            return book;
        }
        return optionalCacheBook;
    }
}
127.0.0.1:6379> keys *
1) "repository-book:2"
2) "repository-book:2:idx"
3) "repository-book"
4) "repository-book:name:apache kafka"
5) "repository-book:name:python"
6) "repository-book:1:idx"
7) "repository-book:1"
127.0.0.1:6379> smembers repository-book:1:idx
1) "repository-book:name:apache kafka"
127.0.0.1:6379> smembers "repository-book:name:apache kafka"
1) "1"

Cache

If there is something in the cache, return it from the cache, if not, find it from the persistent storage, and then write it into the cache. This function can be implemented using Cache

@Slf4j
@Service
@CacheConfig(cacheNames = "cache-book")
public class BookService {
​
    @Autowired
    private BookRepository bookRepository;
​
    @Cacheable
    public List<CacheBook> findAllCoffee() {
        return bookRepository.findAll();
    }
​
    @CacheEvict
    public void reloadCoffee() {
    }
}

Annotation @CacheConfig(cacheNames = “cache-book”) is added to the class. Cacheable and CacheEvict are added to the method. The method of Cacheable is used to implement logic. If there is one, it will be taken from the cache. If not, it will be taken from the database, CacheEvict clears the cache when calling this method. Then add the annotation @EnableJpaRepositories @EnableCaching(proxyTargetClass = true) where the entry program is started, and add it to the configuration file application.properties

Finally

Thanks for reading. I am looking forward to your following and reading more high-quality articles.

Java
Spring
Spring Boot
Jpa
Backend
Recommended from ReadMedium