JPA/休眠:在不存在的序列/关系上选择当前值 [英] JPA/Hibernate: select currval on non existing sequence / relation

查看:171
本文介绍了JPA/休眠:在不存在的序列/关系上选择当前值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在JPA/Hibernate中有一个令人困惑的问题:将值插入表后,对不存在的关系/序列执行select currval().我有两种类似的情况,一种有效,另一种没有.

I have a somehow confusing problem with JPA/Hibernate: a select currval() is performed on a non existing relation/sequence after a value is inserted into the table. I have two similar cases, one works, the other not.

这是第一个无效版本.

实体:

@Entity
@Table(name = "meter")
@Data
@EqualsAndHashCode(callSuper = true)
public class Meter extends AbstractTimestampEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "meter_id")
    private Long meterId;

    @Column(name = "meter_id_str")
    private String meterIdStr;

    @Column(name = "contract_id")
    private Long contractId;

    @Column(name = "user_id")
    private Long userId;

    @Column(name = "com_id")
    private String comId;

    @Column(name = "is_active")
    private Boolean isActive;   
}

Flyway脚本:

CREATE SEQUENCE meter_seq;
CREATE TABLE IF NOT EXISTS meter (
  id           BIGINT NOT NULL DEFAULT nextval('meter_seq'),
  meter_id     BIGINT,
  meter_id_str VARCHAR(20),
  contract_id  BIGINT,
  user_id      BIGINT,
  com_id       VARCHAR(50),
  is_active    BOOLEAN,
  created_at   BIGINT,
  modified_at  BIGINT,
  CONSTRAINT pk_meter PRIMARY KEY (id)
);
ALTER SEQUENCE meter_seq OWNED BY meter.id;

服务:

@Override
@Transactional
public void updateUser(UserDTO userDTO, ContractDTO contractDTO, MeterDTO meterDTO) {
    String meterIdStr = meterDTO.getMeterId();
    long uid = userDTO.getId();
    long cid = contractDTO.getId();
    long mid = meterDTO.getId();
    boolean isActive = meterDTO.isActive();

    log.debug("Updating meter state: {}, isActive: {}, contractId: {}, userId: {}", mid, isActive, cid, uid);

    Meter meter = this.meterRepository.find(uid, cid, meterIdStr);
    if (meter == null) {
        log.debug("No meter found, creating new meter.");
        meter = new Meter();
        meter.setMeterId(mid);
        meter.setMeterIdStr(meterIdStr);
        meter.setContractId(cid);
        meter.setUserId(uid);
        meter.setIsActive(true);
        this.meterRepository.save(meter);
    } else {
        if (isActive != meter.getIsActive()) {
            meter.setIsActive(isActive);
            this.meterRepository.save(meter);
            this.cacheService.evict(CacheNames.METER,
                    new SimpleKey(meter.getMeterIdStr(), meter.getComId()).toString());

            // remove meter from monitoring if it is not active any longer
            if (!isActive) {
                String key = String.format("%d-%d-%d", uid, cid, mid);
                this.boundHashOperations.delete(key);
            }
        }
    }

    log.debug("Done");
}

在插入新的Meter时(在服务类的this.meterRepository.save()行中),我总是会出错:

I always get an error when inserting a new Meter (in line this.meterRepository.save() in the service class):

2018-05-23 06:42:21.303 TRACE - [-enerContainer-4]            o.h.e.j.i.JdbcCoordinatorImpl : Starting after statement execution processing [ON_CLOSE]
2018-05-23 06:42:21.303 DEBUG - [-enerContainer-4]                          o.hibernate.SQL : select currval('meter_data_receiver.meter_id_seq')
2018-05-23 06:42:21.303 TRACE - [-enerContainer-4]   o.h.r.j.i.ResourceRegistryStandardImpl : Registering statement [HikariProxyPreparedStatement@75642772 wrapping select currval('meter_data_receiver.meter_id_seq')]
2018-05-23 06:42:21.304 ERROR - [-enerContainer-4]             o.h.e.j.s.SqlExceptionHelper : FEHLER: Relation „meter_data_receiver.meter_id_seq" existiert nicht

位置:16

没有序列/关系"meter_data_receiver.meter_id_seq".

There is no sequence / relation `meter_data_receiver.meter_id_seq'.

另一种情况类似,但是在这里我可以在日志中看到以下消息:

The other case is similar, but here I can see in the log the following message:

2018-05-23 06:42:21.345 DEBUG - [RedisMessageLis]          o.h.i.IdentifierGeneratorHelper : Natively generated identity: 2

因此,在这种情况下,ID似乎是在插入操作之后从数据库中获取的,而在第一种情况下,对不存在的序列/关系执行了额外的select.

So in this case the ID seems to be taken from the database after the insert operation, whereas in the first case an extra select is performed on a non-existing sequence/relation.

我不知道为什么Hibernate认为它可以通过查询序列来获得第一种情况的ID ...

I have no idea why Hibernate thinks it can get an ID for the first case by querying a sequence...

推荐答案

好,我已经从配置中删除了选项properties.hibernate.temp.use_jdbc_metadata_defaults: false,现在看来可以了.

Ok, I've removed the option properties.hibernate.temp.use_jdbc_metadata_defaults: false from my configuration and now it seems to work.

我不确定为什么要首先添加此选项,我认为有一条警告提示我应该添加此选项...

I'm not sure why I added this option in the first place, I think there was a warning that suggested I should add it...

这篇关于JPA/休眠:在不存在的序列/关系上选择当前值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆