【问题标题】:Updating counters through Hibernate通过 Hibernate 更新计数器
【发布时间】:2011-02-23 21:21:45
【问题描述】:

这是一种极其常见的情况,所以我期待一个好的解决方案。基本上我们需要更新表中的计数器。以网页访问为例:

Web_Page
--------
Id
Url
Visit_Count

所以在hibernate中,我们可能会有这样的代码:

webPage.setVisitCount(webPage.getVisitCount()+1);

mysql默认读取不关注事务的问题。因此,高流量网页的计数会不准确。

我习惯做这种事情的方式就是调用:

update Web_Page set Visit_Count=Visit_Count+1 where Id=12345;

我想我的问题是,我如何在 Hibernate 中做到这一点?其次,如何在 Hibernate 中进行这样的更新,这有点复杂?

update Web_Page wp set wp.Visit_Count=(select stats.Visits from Statistics stats where stats.Web_Page_Id=wp.Id) + 1 where Id=12345;

【问题讨论】:

    标签: sql mysql hibernate transactions counter


    【解决方案1】:

    mysql默认读取不关注事务的问题。因此,高流量网页的计数会不准确。

    的确如此。我会在这里使用 DML 风格的操作(参见章节13.4. DML-style operations):

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    
    String hqlUpdate = "update webPage wp set wp.visitCount = wp.visitCount + 1 where wp.id = :id";
    int updatedEntities = s.createQuery( hqlUpdate )
            .setLong( "newName", 1234l )
            .executeUpdate();
    tx.commit();
    session.close();
    

    这应该会导致

    update Web_Page set Visit_Count=Visit_Count+1 where Id=12345;
    

    其次,如何在 Hibernate 中进行这样的更新,这有点复杂?

    嗯...我很想说“你完蛋了”...需要多考虑一下。

    【讨论】:

    • 谢谢帕斯卡。我不知道我可以在 HQL 中进行更新。看起来很容易。但是对于我更复杂的示例,这是否会成为不关注交易的同一个 SELECT 问题的受害者?你建议我如何处理?
    【解决方案2】:

    stored procedure 有几个好处:

    1. 如果架构发生变化,如果代码是call increment($id),则无需更改代码
    2. 可以本地化并发问题。
    3. 在许多情况下执行速度更快。

    一个可能的实现是:

    create procedure increment (IN id integer)
    begin
        update web_page
          set visit_count = visit_count + 1
          where `id` = id;
    end
    

    【讨论】:

      猜你喜欢
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 2022-12-17
      • 1970-01-01
      • 2018-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多