[英]Best practice for real-world DAOs using @Cacheable annotations
I'm new to Spring and I'm very excited about all the things it offers! 我是Spring的新手,我对它提供的所有东西感到非常兴奋!
Right now, I'm trying to modernize a couple of DAOs in my existing project. 现在,我正在尝试在现有项目中对几个DAO进行现代化。 Specifically, I want to replace my old plain JDBC code with Spring Jdbc support and introduce Spring's transparent caching.
具体来说,我想用Spring Jdbc支持替换旧的纯JDBC代码,并介绍Spring的透明缓存。
First question: am I right that the DAO layer is the right place to add @Cacheable
annotations? 第一个问题:我是否正确DAO层是添加
@Cacheable
注释的正确位置? Or do you do it in the business layer? 或者你在业务层做到了吗?
I can follow all the simple examples to be found on the net. 我可以按照所有简单的例子在网上找到。 However, when it comes to more real world code, I get stuck:
但是,当涉及更多真实世界的代码时,我会陷入困境:
Specifically, I have several methods that return instances of my model Publisher
. 具体来说,我有几个方法返回我的模型
Publisher
实例。 In my manual cache implementations I always made sure only one instance is cached and fetched for the different getPublisher()
methods. 在我的手动缓存实现中,我总是确保只为一个实例缓存并为不同的
getPublisher()
方法提取。 However, using @Cacheable
and trying to encapsulate caching within the DAO, I have the problem, that the annotation doesn't work for local method calls (because of proxying). 但是,使用
@Cacheable
并尝试在DAO中封装缓存,我@Cacheable
的问题是,注释不适用于本地方法调用(因为代理)。
Here's my sample code: 这是我的示例代码:
@Cacheable("publisherCache")
public Publisher getPublisher(int publisherId)
{
String sql = "SELECT * FROM publisher LEFT JOIN publisherContacts USING (publisherId) WHERE publisherId=? ORDER BY publisherContactId ASC";
return getJdbcTemplate().query(sql, publisherResultSetExtractor, publisherId);
}
public List<Publisher> findVisiblePublishers()
{
List<Publisher> publishers = new LinkedList<Publisher>();
for (int publisherId : findVisiblePublisherIds())
{
publishers.add(getPublisher(publisherId));
}
return publishers;
}
@Cacheable(value = "publisherCache", key = "'list'")
private List<Integer> findVisiblePublisherIds()
{
String sql = "SELECT publisherId FROM publisher WHERE isVisible='yes' ORDER BY imprintName";
return getJdbcTemplate().queryForList(sql, Integer.class);
}
public Publisher findNearestPublisher(String appx)
{
appx = "%" + appx + "%";
String sql = "SELECT publisherId FROM publisher WHERE publisherName LIKE ? OR imprintName LIKE ? ORDER BY imprintName DESC LIMIT 1";
Integer publisherId = getJdbcTemplate().queryForObject(sql, Integer.class, appx, appx);
if (publisherId == null)
return null;
else
return getPublisher(publisherId);
}
This was my idea, which as said, doesn't work. 这是我的想法,如上所述,不起作用。
The only alternatives I can see right now are: 我现在能看到的唯一选择是:
a) Only cache the getPublisher(publisherId)
method and define all other methods that return Publisher
s to return int
s (publisherIds), or lists thereof. a)仅缓存
getPublisher(publisherId)
方法并定义返回Publisher
的所有其他方法以返回int
(publisherIds)或其列表。 This doesn't feel natural from an API point of view. 从API的角度来看,这并不自然。 As a service or business logic, I would expect to get instances from the DAO, not only IDs.
作为服务或业务逻辑,我希望从DAO获取实例,而不仅仅是ID。
b) Add @Cacheable
to all methods, duplicating the cache and using more memory than needed (let's assume there are a lot of publishers and that they are heavy objects). b)将
@Cacheable
添加到所有方法,复制缓存并使用比所需更多的内存(让我们假设有很多发布者并且它们是重型对象)。
What is the best practice around this must-be-pretty-common problem? 围绕这个必须非常常见的问题的最佳实践是什么? Thanks for any insights.
感谢您的任何见解。
Common pattern is following: For persistence layer you use hibernate second-level cache. 常见模式如下:对于持久层,您使用休眠二级缓存。 For service layer you use @Cacheable to cache things like long computations or web service call results.
对于服务层,您可以使用@Cacheable来缓存长计算或Web服务调用结果等内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.