У меня есть JPA @Entity с @Id, определенным как
private UUID id;
@Id
@Column(name = "f_id")
@GeneratedValue(generator = "system-uuid")
@Type(type = "pg-uuid")
public UUID getId() {
return id;
}
, и полем @Version, определенным как
private Timestamp lastModified;
@Version
@Column(name = "f_lastmodified")
@Attribute(required = false)
public Timestamp getLastModified() {
return lastModified;
}
результирующий столбец в postgres (сгенерированный hibernate с использованиемcreate-drop) это "метка времени без часового пояса".этот класс используется в приложении, работающем через postgres.при удалении сущности я использую следующий код:
public T delete(UUID id) {
log.debug("deleting entity {}", id);
EntityManager em = ... //get from somewhere
em.flush(); //make sure we're in sync with DB
T object = em.find(getClassType(), id); //get latest version
if (object == null) {
throw new IllegalStateException("could not find an entity with id "+id);
}
em.refresh(object);
em.remove(object);
em.flush();
return object;
}
Раньше было проще найти (type, id) + remove, но я добавил дополнительный пух, пытаясь заставить его работать.проблема в том, что приведенный выше код не работает.ошибка, отображаемая в журнале:
08:25:15,940 INFO [STDOUT] Hibernate:
08:25:15,950 INFO [STDOUT] delete
08:25:15,950 INFO [STDOUT] from
08:25:15,950 INFO [STDOUT] dpa.filesystem_status
08:25:15,950 INFO [STDOUT] where
08:25:15,950 INFO [STDOUT] f_id=?
08:25:15,960 INFO [STDOUT] and f_lastmodified=?
08:25:45,123 ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session: org.hibernate.StaleObjec
tStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [FilesystemStatus#78c839f0-0b12-4df6-b9ec-ac1e52e9b1f1]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1950) [:3.6.1.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2710) [:3.6.1.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2911) [:3.6.1.Final]
после некоторой отладки, я думаю, что я нашел основную причину проблемы: сущность, которую я пытался удалить, имеет NULL в поле версии.hibernate создает подготовленный оператор для удаления (который напечатан в приведенном выше фрагменте журнала), правильно устанавливает идентификатор и затем устанавливает NULL для поля версии (также логически корректно).код hibernate, который делает это, находится в строке 78 BasicBinder.java (ядро hibernate 3.6.1)
st.setNull( index, sqlDescriptor.getSqlType() );
, второй аргумент разрешается до 93 во время выполнения.в конце концов, запуск подготовленного оператора приводит к удалению 0 строк, а спящий режим принимает его, потому что "f_lastmodified =?"part не совпадает и решает, что кто-то должен совершить другую временную метку между ними (== устаревшая сущность передана для удаления).это не правда.
как мне продолжить отсюда?
более конкретно:1. Как я узнаю, что 93 правильный тип sql для передачи в setNull ()?Где я могу найти таблицу "правильных" типов SQL?это специфично для БД (что означает, что я должен посмотреть в postgres docs) или какой-то стандарт JDBC?2. как мне решить проблему?я не могу гарантировать нулевой столбец @Version, поэтому мне нужен этот сценарий для работы3. это известная проблема hibernate / postgresql-jdbc-driver, которую я пропустил?Я использую jdk 1.6u24 x64 на win7 x64, jboss 6.1-snapshot, hibernate 3.6.1.final, postgres 9.0, драйвер postgres jdbc4 9.0-801