У меня несколько запутанная проблема с JPA / Hibernate: select currval()
выполняется для несуществующего отношения / последовательности после того, как значение вставлено в таблицу.У меня есть два подобных случая, один работает, другой нет.
Вот первая, нерабочая версия.
Объект:
@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()
в классе обслуживания) всегда появляется ошибка:
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 '.
Другой случай аналогичен, но здесь я вижу в журнале следующее сообщение:
2018-05-23 06:42:21.345 DEBUG - [RedisMessageLis] o.h.i.IdentifierGeneratorHelper : Natively generated identity: 2
Таким образом, в этом случае кажется, что идентификатор извлекается из базы данных после операции вставки, тогда как в первом случае дополнительная select
выполняется для несуществующей последовательности / отношения.
Понятия не имею, почему Hibernate считает, что может получить идентификатор для первого случая, запросив последовательность ...