繁体   English   中英

如何使用Hibernate控制INSERT语句中的并发

[英]How to control concurrency in INSERT statements using Hibernate

通过Web应用程序插入数据时,我无法控制并发性。

上下文:我有3个表(X,Y和Z)记录患者的住院情况。 病人不能接受多于一次的积极住院治疗。

目前,我的应用程序在数据库中的住院INSERT之前进行了验证,以检查患者是否已经住院。

但是,当两个或多个用户尝试同时接纳同一名患者时,此验证无效。

我现在应该做什么:

1 - verify if patient is already hospitalized (SELECT in table X)
  If not:
    begin transaction A;
      2 - INSERT in table X;
      3 - INSERT in table Y;
      4 - INSERT in table Z;
    end transaction A;

正如我之前提到的,在1中进行的验证旨在避免患者两次或更多次入院。 但是,如果两个(或更多)用户尝试同时接纳同一名患者,则该方法将不起作用。

也许我可以使用某些东西来锁定SELECT语句,直到事务A完成为止。 这样,SELECT将在执行时识别患者已经登记。

我想使用数据库中PostgreSQL的EXPLICITING LOCKING处理这个问题。 根据文档,我可以使用ACCESS EXCLUSIVE锁定模式执行类似的操作(因为它是唯一可以锁定select语句的模式)。

但是如何在Hibernate中实现此ACCESS EXCLUSIVE锁?

我已经检查过了,无法使用数据库中的约束来解决这个问题

你尝试了什么? 您的问题提到了postgres。 在这里检查了他们的文档。 如果要从数据库方面解决问题,可以尝试按照其规范中定义的可序列化隔离级别尝试事务。

在他们的文档中,使用此隔离级别无法进行脏读,幻像读和不可重复读。

另外,如果您想解决Java问题,则可以围绕所需的任何类进行同步服务包装,以提供适当的同步逻辑。 所以如果你有

public interface MyService {
    public void hospitalize(Patient patient) throws Exception;
    // etc
}

public class MyServiceImpl implements MyService {
    @Transactional
    public void hospitalize(Patient patient) throws Exception {
        // your logic
    }
}

public MyServiceSerialImpl extends MyServiceImpl {
    @Override
    @Transactional
    public void hospitalize(Patient patient) throws Exception {
        // ...
        synchronized (lock) {
            super.hospitalize(patient);
        }

        // ...
    }

    private final Object lock = new Object();
}

或整个方法同步,或类似的方法。

编辑

正如Roman Konoval在评论中所指出的那样, 如果存在多个应用程序,一个集群,多个jvm等,那么Java同步解决方案将无济于事 。您需要在数据库中工作。

为了确保单个患者不能有两次住院,您需要在字段中添加唯一约束,该约束是从X(和/或Y,Z)到患者的引用(我假设已经有一个如patient_id的字段)至少在这些表格之一中,否则您将如何参考插入X,Y和Z的记录的患者。

在这种情况下,数据库将确保您不能将给定患者的多个记录插入表中。

您需要捕获唯一的违反约束的异常,并做任何想做的事情,以防万一住院已经存在。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM