【问题标题】:Need to solve a query cache problem需要解决一个查询缓存问题
【发布时间】:2011-03-27 14:24:47
【问题描述】:

我正在开发一个复式记帐系统,我需要在顺序 ID 中插入没有任何间隙的过帐记录。由于所有数据库访问都将通过 Web 应用程序进行,因此我使用同步静态变量来处理 id 生成:

import org.hibernate.*;

public class JournalService {    
    private static Object journalLock = new Object();    
    private Session session;

    public JournalService(Session session) {
        this.session = session;
    }

    public void insertJournalEntry(JournalEntry journalEntry) {
        Set<PostEntry> entries = journalEntry.getEntries();

        double total = 0;

        for (PostEntry entry : entries) {
            total += entry.getAmount();
        }

        if(total != 0)
            throw new InvalidParameterException("Journal entry is invalid. The sum of all entries must be zero.");

        Criteria criteria = session.createCriteria(PostEntry.class);
        criteria.setMaxResults(1);
        criteria.addOrder(Order.desc("id"));
        //here I add some other criteria
        synchronized(journalLock) {            
            PostEntry lastEntry = criteria.uniqueResult();
            long currentId = lastEntry.getId();

            for (PostEntry entry : entries) {
                entry.setId(currentId++)
                session.save(entry);
            }            
            session.save(journalEntry);
        }
    }
}

简而言之,该服务的生命周期与当前的 httprequest 相关联,并由 spring 容器管理,此外我确保整个事务在请求结束时提交。同步块将处理任何并发,因此在 id 的序列中不会发生任何间隙。 这里最大的问题是增加了数据库访问的开销,用于选择与特定条件匹配的最后插入的记录。我不希望这种情况发生,所以我猜这里的解决方案是使用缓存,该缓存将在第一次选择时保存最后插入的记录,因此生成 id 不需要数据库访问。 我的问题:有没有开箱即用的休眠方式来解决这个问题?我是休眠新手,听说过查询缓存,但我不确定如何使用它。我不希望缓存保存我使用此服务存储的每个值,我只需要它来存储与特定条件匹配的最后插入的条目。例如,如果我执行了五次插入,其中两个匹配相同的条件“X”,另外三个匹配条件“Y”,缓存将只存储两个对象(匹配每个条件的最后插入的对象)。 我自己可以轻松实现,但我更愿意使用与 hibernate API 集成的解决方案。

【问题讨论】:

    标签: java hibernate second-level-cache query-cache


    【解决方案1】:

    缓存更适合存储经常访问的但很少修改的对象。它不是你想要做的。您可以使用可序列化的事务来防止丢失更新和不一致的读取,这是您要避免的。但是你应该记住它的开销。

    // Hibernate Transaction isolation level settings
    // Serializable isolation level
    hibernate.connection.isolation=8
    

    SessionFactory API 是这样说的

    SessionFactory 的行为由在配置时提供的属性控制。这些属性是在环境中定义的。

    作为解决方法,您可以设置两个不同的 SessionFactory,其中一个是可序列化的,如上所示。

    因为您正在检索最新插入的 PostEntry 实体,所以我认为悲观主义锁定无法正确应用,因为您的数据库只是锁定了检索到的 PostEntry。

    【讨论】:

    • 实际上,我主要关心的是避免额外的数据库查询来获取符合特定条件的最后插入的对象,我不太关心丢失插入,因为它们总是在请求结束时发生.你能举一个更具体的例子来说明你所说的话吗?我没有完全理解你描述的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    相关资源
    最近更新 更多