Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在读写操作之间锁定表_Java_Hibernate_Jpa_Transactions_Locking - Fatal编程技术网

Java 如何在读写操作之间锁定表

Java 如何在读写操作之间锁定表,java,hibernate,jpa,transactions,locking,Java,Hibernate,Jpa,Transactions,Locking,我遇到的情况是,每个新记录都应该包含一个唯一且可读的值。 该值对用户具有业务意义,并将在数据库中作为自然id(主键旁边)处理 要让您了解价值结构,请执行以下操作: - record 1 has business value 'INVOICE_AAA_001' - record 2 has business value 'INVOICE_AAA_002' ... - record 999 has business value 'INVOICE_AAA_999' - record 1

我遇到的情况是,每个新记录都应该包含一个唯一且可读的值。 该值对用户具有业务意义,并将在数据库中作为自然id(主键旁边)处理

要让您了解价值结构,请执行以下操作:

 - record 1 has business value 'INVOICE_AAA_001'
 - record 2 has business value 'INVOICE_AAA_002'
   ...
 - record 999  has business value 'INVOICE_AAA_999'
 - record 1000 has business value 'INVOICE_BAA_001'
 - record 1001 has business value 'INVOICE_BAA_002'
   ...
该业务价值由工厂创造:

class BusinessFactory {

    ...    

    public String createUniqueValue() {
        String lastValue = (String) getSession().createQuery("select businessValue " + 
                                                             "from Invoice as invoice " + 
                                                             "order by businessValue")
                                                .setMaxResults(1)
                                                .setReadOnly(true)
                                                .uniqueResult();    

       // generate new value 

       return newValue;
    }

}
服务层将调用工厂并保存新发票:

  @Transactional
  public void saveNewInvoice() {
      final String newValue = businessFactory.createUniqueValue();        
      Invoice invoice = new Invoice(newValue);
      invoiceRepository.save(invoice);
  }
这里的问题是可能存在这样一种情况,即trx1和trx2读取业务价值“发票_BAA_002”。 接下来发生的是两个trx使用相同的值。第一次提交的trx将成功,第二次将由于唯一约束异常而失败

因此,我需要在读取最新业务价值时锁定发票表。我认为在将新发票实体保存到DB之前,此锁应该处于活动状态


在Hibernate中应该如何执行此操作?

序列是一组整数1、2、3、。。。按需按顺序生成的。序列经常在数据库中使用,因为许多应用程序要求表中的每一行都包含唯一的值,而序列提供了一种生成序列的简单方法

你能做的一件事

class BusinessFactory {
public String createUniqueValue() {
    String valueNotUsed = (String) getSession().createSQLQuery("select nextval('hibernate_sequence')");    

   // generate new value 

   return newValue;
}}

您可以使用悲观锁定,而不是使用冲突检测并发控制机制(例如依赖于唯一约束或约束)

您需要:

  • 带有映射到它的实体的
    InvoiceSequence

  • 此表只有一行,存储最新的发票序列值

  • 请记录在案:

    InvoiceSequence invoiceSequence = em.find(InvoiceSequence.class, 1L, LockModeType.PESSIMISTIC_WRITE)
    
  • 使用业务逻辑增加序列,并修改实体以存储最新值:

    String currentSequence = invoiceSequence.getValue();
    String nextSequence = sequenceGenerator.nextValue(currentSequence);
    invoiceSequence.setValue(nextSequence);
    

  • 独占锁也将防止并发读写。

    序列可以帮助您。你能创建一个吗?我不知道如何创建序列。你能给我更多的信息吗?序列是否阻止两个使用相同值的并发事务?此处的名称
    lastUniqueValue
    具有误导性,因为您获得的值已经是未使用的值。
    nextval
    返回下一个未使用的值,以便您可以直接使用。感谢您的回复。nextval(“hibernate_序列”)是hibernate还是特定于数据库?这项功能是否适用于所有关于防止方言的数据库?请参阅:再次感谢您的回复。但我怀疑“nextval”在这种情况下是否有用,因为我还必须管理字母数字位置(AAA、BAA、BBA…),因此我认为我确实需要读取最新插入记录的业务价值并应用锁。您可以捕获最后插入的记录以生成字母。然后得到序列的一个新值,并和字母STHX合并为您的答案!我想我必须定义某种类型的锁超时,以防止另一个trx不确定地等待,并确保锁将被释放?也许我还应该添加一个特性,自动重试由于锁定超时而失败的trx?