Подтвердить что ты не робот

Hibernate: как исправить "идентификатор экземпляра, измененного с X на Y"?

org.hibernate.HibernateException: identifier of an instance 
of org.cometd.hibernate.User altered from 12 to 3

на самом деле, моя таблица user действительно должна динамически изменять ее значение, мое приложение Java многопоточно. Есть идеи, как это исправить?

4b9b3361

Ответ 1

Вы меняете значение первичного ключа для объекта User где-то? Вы не должны этого делать. Убедитесь, что правильное отображение для первичного ключа.

Как выглядит ваше сопоставление XML файла или аннотации сопоставления?

Ответ 2

Вы должны отделить свою сущность от сеанса до изменения ее полей идентификатора

Ответ 3

В моем случае поле PK в файле hbm.xml имело тип "integer", но в коде bean оно было long.

Ответ 4

В моем случае я решил, что он меняет тип поля @Id от long до Long.

Ответ 5

В моем конкретном случае это было вызвано методом в моей реализации службы, который нуждался в аннотации spring @Transactional(readOnly = true). Как только я добавил, проблема была решена. Необычно, но это был просто оператор select.

Ответ 6

В моем случае шаблон имел опечатку, поэтому вместо проверки эквивалентности (==) он использовал присваивание равно (=).

Итак, я изменил логику шаблона:

if (user1.id = user2.id) ...

to

if (user1.id == user2.id) ...

и теперь все в порядке. Итак, проверьте свои взгляды!

Ответ 7

В моем случае имена getters и setter отличались от имени переменной.

private Long stockId;
    public Long getStockID() {
        return stockId;
    }
    public void setStockID(Long stockID) {
        this.stockId = stockID;
    }

где он должен быть

public Long getStockId() {
    return stockId;
}
public void setStockId(Long stockID) {
    this.stockId = stockID;
}

Ответ 8

Убедитесь, что вы не пытаетесь использовать один и тот же объект пользователя несколько раз при изменении идентификатора. Другими словами, если вы делали что-то в операции типа пакета:

User user = new User();  // Using the same one over and over, won't work
List<Customer> customers = fetchCustomersFromSomeService();
for(Customer customer : customers) {
 // User user = new User(); <-- This would work, you get a new one each time
 user.setId(customer.getId());
 user.setName(customer.getName());
 saveUserToDB(user);
}

Ответ 9

Я тоже столкнулся с этой проблемой.

Таблица целей - таблица отношений, проводящая два идентификатора из разных таблиц. У меня есть УНИКАЛЬНОЕ ограничение на комбинацию значений, заменяя ПК. При обновлении одного из значений кортежа эта ошибка возникла.

Вот как выглядит таблица (MySQL):

CREATE TABLE my_relation_table (
  mrt_left_id BIGINT NOT NULL,
  mrt_right_id BIGINT NOT NULL,
  UNIQUE KEY uix_my_relation_table (mrt_left_id, mrt_right_id),
  FOREIGN KEY (mrt_left_id)
    REFERENCES left_table(lef_id),
  FOREIGN KEY (mrt_right_id)
    REFERENCES right_table(rig_id)
);

Класс Entity для объекта RelationWithUnique выглядит в основном следующим образом:

@Entity
@IdClass(RelationWithUnique.class)
@Table(name = "my_relation_table")
public class RelationWithUnique implements Serializable {

  ...

  @Id
  @ManyToOne
  @JoinColumn(name = "mrt_left_id", referencedColumnName = "left_table.lef_id")
  private LeftTableEntity leftId;

  @Id
  @ManyToOne
  @JoinColumn(name = "mrt_right_id", referencedColumnName = "right_table.rig_id")
  private RightTableEntity rightId;

  ...

Я зафиксировал его на

// usually, we need to detach the object as we are updating the PK
// (rightId being part of the UNIQUE constraint) => PK
// but this would produce a duplicate entry, 
// therefore, we simply delete the old tuple and add the new one
final RelationWithUnique newRelation = new RelationWithUnique();
newRelation.setLeftId(oldRelation.getLeftId());
newRelation.setRightId(rightId);  // here, the value is updated actually
entityManager.remove(oldRelation);
entityManager.persist(newRelation);

Большое спасибо за намек на ПК, я просто пропустил его.

Ответ 10

Проблема может быть также в разных типах объектов PK ( "Пользователь" в вашем случае) и введите, что вы запрашиваете hibernate для получения session.get(type, id);.

В моем случае ошибка была identifier of an instance of <skipped> was altered from 16 to 32. Тип объекта PK был Integer, для спящего режима был задан тип Long.

Ответ 11

В моем случае это было потому, что свойство было длинным на объекте, но int в сопоставлении xml, это исключение должно быть более ясным

Ответ 12

Если вы используете Spring MVC или Spring Boot, попробуйте избежать: @ModelAttribute ( "пользователь" ) в одном контролере и в другом контроллере model.addAttribute( "пользователь", userRepository.findOne(someId);

Эта ситуация может вызвать такую ​​ошибку.

Ответ 13

Это старый вопрос, но я собираюсь добавить исправление для моей конкретной проблемы (Spring Boot, JPA с помощью Hibernate, SQL Server 2014), поскольку он не совсем соответствует другим приведенным здесь ответам:

У меня был внешний ключ, например. my_id = '12345', но значение в столбце с ссылкой было my_id = '12345'. В конце было дополнительное пространство, спящий режим которого не понравился. Я удалил пространство, исправил часть моего кода, которая позволяла это дополнительное пространство, и все работает нормально.

Ответ 14

Столкнулся с той же проблемой. У меня была ассоциация между 2 бобами. В bean AI определен тип переменной как Integer, а в bean BI определена та же переменная, что и в Long. Я изменил их обоих на Integer. Это решило мою проблему.

Ответ 15

Это проблема в вашем методе обновления. Просто сохраните изменения, прежде чем сохранить изменения, и все будет в порядке. Если вы используете отображение между DTO и классом Entity, сделайте это перед отображением.

У меня тоже была эта ошибка. У меня был пользовательский объект, пытающийся изменить его местоположение, местоположение было FK в пользовательской таблице. Я решил эту проблему с

@Transactional
public void update(User input) throws Exception {

    User userDB = userRepository.findById(input.getUserId()).orElse(null);
    userDB.setLocation(new Location());
    userMapper.updateEntityFromDto(input, userDB);

    User user= userRepository.save(userDB);
}