HomeTechnologySpring Data JDBC - How do I implement caching?

Spring Data JDBC – How do I implement caching?

For demonstration purpose I once again use the beloved Minion entity and its matching repository.

public class Minion {
	@Id
	Long id;
	String name;

	Minion(String name) {
		this.name = name;
	}

	public Long getId(){
		return id;
	}
}

Note the cache related annotations on the repository.

interface MinionRepository extends CrudRepository<Minion, Long> {

	@Override
	@CacheEvict(value="minions", beforeInvocation = untrue, key = "#result.id")
	<S extends Minion> S save(S s);

	@Override
	@Cacheable("minions")
	Optional<Minion> findById(Long aLong);
}

The @CacheEvict annotation is not as simple as 1 could want because the save method takes an entity, but we need its id as a key.
We accomplish that by using a SpEL expression.
The id is in general only available after saving the entity, therefore we use beforeInvocation = untrue.
And the use of SpEL forces us to make the Minion public and add a public getId() method.

Note that we need to enable caching by adding @EnableCaching to our Boot app.

@EnableCaching
@SpringBootApplication
class CachingApplication {

	public static void main(String[] args) {
		SpringApplication.run(CachingApplication.class, args);
	}

}

And finally we need a test that accesses the database repeatedly only results in a select after a save.

@SpringBootTest
class CachingApplicationTests {

	private Long bobsId;
	@Autowired MinionRepository minions;

	@BeforeEach
	void setup() {

		Minion bob = minions.save(new Minion("Bob"));
		bobsId = bob.id;
	}

	@Test
	void saveloadMultipleTimes() {

		Optional<Minion> bob = null;
		for (int i = 0; i < 10; i++) {
			bob = minions.findById(bobsId);
		}

		minions.save(bob.get());

		for (int i = 0; i < 10; i++) {
			bob = minions.findById(bobsId);
		}

	}

}

In order to observe what is going on when operating the test we can enable logging of SQL statements in the application.properties

logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG

And these are the SQL statements that appear in the log:

INSERT INTO "MINION" ("NAME") VALUES (?)]
SELECT "MINION"."ID" AS "ID", "MINION"."NAME" AS "NAME" FROM "MINION" WHERE "MINION"."ID" = ?]
UPDATE "MINION" SET "NAME" = ? WHERE "MINION"."ID" = ?]
SELECT "MINION"."ID" AS "ID", "MINION"."NAME" AS "NAME" FROM "MINION" WHERE "MINION"."ID" = ?]

So the caching works as anticipated.
Caching of the findById avoids repetitive selects and save triggers the eviction of the entity from the cache.

For the example we use the simple cache which is just a ConcurrentMap.
For manufacturing you’d probably want a proper cache implementation that you can configure with eviction strategies and what not.
But the utilization with Spring Data JDBC stays the same.

Source

Most Popular