问题描述
我在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/休眠:在不存在的序列/关系上选择当前值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!