如何为Postgres配置休眠隔离级别

时间:2019-08-06 07:43:28

标签: postgresql hibernate jpa

我在postgres数据库中有一个表ErrorCase。该表具有一个带有数据类型文本的字段case_id。其值由以下格式生成:yymmdd_xxxx。 yymmdd是记录插入数据库的日期,xxxx是该日期的记录数。

例如,在2019/08/01的第3个错误情况下,case_id = 190801_0003。在08/04,如果还有一种情况,其case_id将为190804_0001,然后继续。

我已经在数据库中使用触发器来为此字段生成值:

DECLARE
    total integer;
BEGIN
    SELECT (COUNT(*) + 1) INTO total  FROM public.ErrorCase WHERE create_at = current_date;
    IF (NEW.case_id is null) THEN 
        NEW.case_id = to_char(current_timestamp, 'YYMMDD_') || trim(to_char(total, '0000'));
    END IF;
    RETURN NEW;
END

在Spring Project中,我为jpa / hibernates配置了应用程序属性:

datasource:
        type: com.zaxxer.hikari.HikariDataSource
        url: jdbc:postgresql://localhost:5432/table_name
        username: postgres
        password: postgres
        hikari:
            poolName: Hikari
            auto-commit: false
    jpa:
        database-platform: io.github.jhipster.domain.util.FixedPostgreSQL82Dialect
        database: POSTGRESQL
        show-sql: true
        properties:
            hibernate.id.new_generator_mappings: true
            hibernate.connection.provider_disables_autocommit: true
            hibernate.cache.use_second_level_cache: true
            hibernate.cache.use_query_cache: false
            hibernate.generate_statistics: true

当前,它可以正确生成case_id。

但是,当几乎同时插入许多记录时,它将为两个记录生成相同的case_id。我想原因是因为隔离级别。当第一个事务尚未提交时,第二个事务执行SELECT查询以建立case_id。因此,SELECT查询的结果不包括第一个查询的记录(因为它尚未提交)。因此,第二个case_id具有与第一个相同的结果。

请给我建议解决此问题的任何方法,哪种隔离级别适合这种情况??

1 个答案:

答案 0 :(得分:0)

yymmdd是记录插入DB的日期,xxxx是该日期的记录数”-没有冒犯,但这是一个可怕的设计。

您应该有两个单独的列,一个public function __construct(AWSTranslationService $awsTranslator) { $this->awsTranslator = $awsTranslator; } 列和一个date列。如果要在插入过程中增加计数器,请将该日期列作为主键并使用integer。您可以摆脱那些效率低下的触发器,更重要的是,即使提交了读操作,对于并行修改也是安全的。

类似的东西:

insert on conflict

然后使用以下内容插入行:

create table error_case
(
  error_date date not null primary key, 
  counter integer not null default 1
);

不需要触发器,并且对于并发插入是安全的。

如果您确实需要文本列作为“案例ID”,请创建一个返回该格式的视图:

insert into error_case (error_date)
values (date '2019-08-01')
on conflict (error_date) do update 
   set counter = counter + 1;
相关问题