java - Q : hibernate spring transaction is synchronized ? 如果没有,我如何更新数据库安全线程?

标签 java sql spring hibernate sqltransaction

我的问题是,首先,hibernate spring事务是否同步?

如果不是,如果我同时使用同一个对象开始两个事务,会发生什么?

我很乐意向您展示这个示例:

我有一个 Player 对象和一个 Ship 对象

玩家

  • 黄金
  • 设置船只

发货

  • 实际价格

我有一个这样的方法:

session.beingTrasaction()

// if player have enough gold, start one query to set gold to gold-price, and second query to add new ship

session.getTransaction().commit();

这可以安全使用吗?如果我使用同一个玩家多次调用这样的算法,它们会串行执行吗?

非常欢迎任何帮助或解释

解决方案:

感谢我在这里得到的帮助,我通过使用 hibernate locking 找到了我的解决方案,我选择使用悲观锁,其实也挺简单的。

就我而言,这是我的实现:

我添加到播放器:

private Long databaseVersion;

@Version
public Long getDatabaseVersion() {
    return databaseVersion;
}
public void setDatabaseVersion(Long databaseVersion) {
        this.databaseVersion = databaseVersion;
}

还有我的 dao 工具:

public void buyShip(Player player, Ship ship) {
    Session session = sessionFactory.openSession();
    session.beginTransaction();

    Player p = (Player) session.get(Player.class, player.getId(), LockMode.PESSIMISTIC_WRITE);

    if(p.getGold()>=ship.getPrice()) {
        ship.setPlayer(player);
        addShipToUser(session,ship);

        p.setGold(player.getGold()-ship.getPrice());
        session.update(p);
    }else {
        System.out.println("NOT EN GOLD");
    }


    session.getTransaction().commit();
    session.close();
}

我用 5 个线程检查它,它工作了!我对同一播放器的所有更改都将串行执行,而对不同播放器的更改将并行执行!

最佳答案

不存在 Spring 事务这样的东西。 Spring仅为事务管理提供一致的抽象来启动和提交/回滚事务。

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(
            TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

但是您必须将管理实际事务的实际实现注入(inject)其中。例如,hibernate 事务的抽象是 HibernateTransactionManager,并且您必须注入(inject) Hibernate 的 SessionFactory,后者执行实际的开始/提交/回滚操作。

除此之外,如果两个线程执行同一个事务:

session.beingTrasaction()

if (player.gold > 10){
   player.setGold(gold - 10);
   Ship newShip = new Ship();
   player.addShip(newShip);  // I suppose you have cascade insert otherwise you have to save your transient ship
}

session.getTransaction().commit();

事务将以串行方式提交。但是,您最终可能会遇到金币数量为负的玩家。

Thread 1                                 Thread 2 
if (player.gold > 10) // true           
                                         if (player.gold > 10) // true
player.gold = gold - 10 // gold=0
                                         player.gold = gold - 10 // gold=-10

您需要optimisticpessimistic锁定。

关于java - Q : hibernate spring transaction is synchronized ? 如果没有,我如何更新数据库安全线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42585379/

相关文章:

Spring CGLib 和 EasyMock - 尝试重复的类定义

spring - 在 Spring Security 3.2.5 中,是什么导致 AuthenticationManager 实现内部出现无限循环?

java - 我可以使用什么将 Java 连接到 Video4Linux?

java - 如何让commons VFS永久运行

java - MusixMatch API 和 GSON : Using track. snippet.get 而不是 track.lyrics.get

php - 需要 MySQL 优化以对 EAV 结构化数据进行复杂搜索

java - 如何从 PreparedStatement 中获取参数?

MySQL GROUP CONCAT 重复项

php - Sql从两个表中获取数据

java - spring aop FastClassBySpringCGLIB 与EnhancerBySpringCGLIB