5

我是 Spring 的新手,我对它提供的所有东西感到非常兴奋!

现在,我正在尝试对现有项目中的几个 DAO 进行现代化改造。具体来说,我想用 Spring Jdbc 支持替换旧的纯 JDBC 代码,并引入 Spring 的透明缓存。

  1. @Cacheable第一个问题:DAO 层是添加注释的正确位置,我说得对吗?还是在业务层做?

  2. 我可以按照在网上找到的所有简单示例进行操作。但是,当涉及到更多真实世界的代码时,我会陷入困境:

具体来说,我有几个方法可以返回我的模型实例Publisher。在我的手动缓存实现中,我总是确保只有一个实例被缓存并为不同的getPublisher()方法获取。但是,@Cacheable在 DAO 中使用并尝试封装缓存时,我遇到了一个问题,即注释不适用于本地方法调用(因为代理)。

这是我的示例代码:

@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);
}

这是我的想法,如前所述,行不通。

我现在能看到的唯一选择是:

a) 仅缓存该getPublisher(publisherId)方法并定义所有其他返回 s 的方法Publisher以返回ints (publisherIds) 或其列表。从 API 的角度来看,这并不自然。作为服务或业务逻辑,我希望从 DAO 中获取实例,而不仅仅是 ID。

b)添加@Cacheable到所有方法,复制缓存并使用比需要更多的内存(假设有很多发布者并且它们是重对象)。

围绕这个必须非常常见的问题的最佳实践是什么?感谢您的任何见解。

4

1 回答 1

0

常见模式如下:对于持久层,您使用休眠二级缓存。对于服务层,您使用 @Cacheable 来缓存长计算或 Web 服务调用结果等内容。

于 2013-06-11T14:10:08.240 回答