Hibernate:如何修复“实例的标识符从 X 更改为 Y”?

发布于 2024-10-02 05:35:52 字数 212 浏览 4 评论 0原文

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

事实上,我的 user 表确实必须动态更改其值,我的 Java 应用程序是多线程的。 有什么想法如何修复它吗?

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

in fact, my user table is really must dynamically change its value, my Java app is multithreaded.
Any ideas how to fix it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

[浮城] 2024-10-09 05:35:52

您是否在某处更改了 User 对象的主键值?你不应该这样做。检查主键的映射是否正确。

您的映射 XML 文件或映射注释是什么样的?

Are you changing the primary key value of a User object somewhere? You shouldn't do that. Check that your mapping for the primary key is correct.

What does your mapping XML file or mapping annotations look like?

遮了一弯 2024-10-09 05:35:52

在修改实体的 ID 字段之前,您必须将实体与会话分离

You must detach your entity from session before modifying its ID fields

等数载,海棠开 2024-10-09 05:35:52

就我而言,hbm.xml 中的 PK 字段的类型为“integer”,但在 bean 代码中它是 long

In my case, the PK Field in hbm.xml was of type "integer" but in bean code it was long.

〃温暖了心ぐ 2024-10-09 05:35:52

就我而言,getter 和 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;
}

In my case getters and setter names were different from Variable name.

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

where it should be

public Long getStockId() {
    return stockId;
}
public void setStockId(Long stockID) {
    this.stockId = stockID;
}
酒解孤独 2024-10-09 05:35:52

也遇到了此错误消息,但根本原因与此处其他答案中引用的内容不同。

通用答案:
确保一旦 hibernate 加载实体,任何代码都不会以任何方式更改该对象中的主键值。当 hibernate 将所有更改刷新回数据库时,它会抛出此异常,因为主键发生了更改。如果您没有明确执行此操作,请查找可能无意中发生这种情况的位置,可能是在仅配置了延迟加载的相关实体上。

就我而言,我使用映射框架 (MapStruct) 来更新实体。在此过程中,其他引用的实体也会更新,因为映射框架默认会这样做。后来我用新实体替换了原始实体(在数据库术语中,更改了外键的值以引用相关表中的不同行),先前引用的实体的主键已经更新,并且休眠尝试在刷新时保留此更新。

Also ran into this error message, but the root cause was of a different flavor from those referenced in the other answers here.

Generic answer:
Make sure that once hibernate loads an entity, no code changes the primary key value in that object in any way. When hibernate flushes all changes back to the database, it throws this exception because the primary key changed. If you don't do it explicitly, look for places where this may happen unintentionally, perhaps on related entities that only have LAZY loading configured.

In my case, I am using a mapping framework (MapStruct) to update an entity. In the process, also other referenced entities were being updates as mapping frameworks tend to do that by default. I was later replacing the original entity with new one (in DB terms, changed the value of the foreign key to reference a different row in the related table), the primary key of the previously-referenced entity was already updated, and hibernate attempted to persist this update on flush.

多彩岁月 2024-10-09 05:35:52

在我的特定情况下,这是由我的服务实现中的一个方法引起的,该方法需要 spring @Transactional(readOnly = true) 注释。我添加后,问题就解决了。但不同寻常的是,这只是一条 select 语句。

In my particular case, this was caused by a method in my service implementation that needed the spring @Transactional(readOnly = true) annotation. Once I added that, the issue was resolved. Unusual though, it was just a select statement.

南街女流氓 2024-10-09 05:35:52

就我而言,我解决了将 @Id 字段类型从 long 更改为 Long 的问题。

In my case, I solved it changing the @Id field type from long to Long.

稚气少女 2024-10-09 05:35:52

确保在更改 ID 时不会多次尝试使用同一个 User 对象。换句话说,如果您在批处理类型操作中执行某些操作:

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);
}

Make sure you aren't trying to use the same User object more than once while changing the ID. In other words, if you were doing something in a batch type operation:

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);
}
小镇女孩 2024-10-09 05:35:52

是你的更新方法有问题。只需在保存更改之前实例化新用户即可。如果您在 DTO 和实体类之间使用映射,请在映射之前执行此操作。

我也有这个错误。我有用户对象,试图更改他的位置,位置在用户表中是 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);
}  

It is a problem in your update method. Just instance new User before you save changes and you will be fine. If you use mapping between DTO and Entity class, than do this before mapping.

I had this error also. I had User Object, trying to change his Location, Location was FK in User table. I solved this problem with

@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);
}  
卸妝后依然美 2024-10-09 05:35:52

就我而言,模板有一个拼写错误,因此它没有检查等效性 (==),而是使用赋值等于 (=)。

所以我将模板逻辑从: 更改

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

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

,现在一切都很好。所以,也检查一下你的观点!

In my case, a template had a typo so instead of checking for equivalency (==) it was using an assignment equals (=).

So I changed the template logic from:

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

to

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

and now everything is fine. So, check your views as well!

雨后咖啡店 2024-10-09 05:35:52

我也面临这个问题。

目标表是一个关系表,连接来自不同表的两个 ID。我对值组合有一个唯一的约束,替换了 PK。
当更新元组的值之一时,发生此错误。

这就是表的样子(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)
);

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);

非常感谢 PK 的提示,我只是错过了它。

I was facing this issue, too.

The target table is a relation table, wiring two IDs from different tables. I have a UNIQUE constraint on the value combination, replacing the PK.
When updating one of the values of a tuple, this error occured.

This is how the table looks like (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)
);

The Entity class for the RelationWithUnique entity looks basically like this:

@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;

  ...

I fixed it by

// 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);

Thanks a lot for the hint of the PK, I just missed it.

予囚 2024-10-09 05:35:52

问题也可能出在不同类型的对象的 PK(在您的情况下为“用户”)并键入您要求 hibernate 获取 session.get(type, id);

在我的例子中,错误是实例的标识符。从 16 更改为 32
对象的 PK 类型是 Integer,hibernate 被要求使用 Long 类型。

Problem can be also in different types of object's PK ("User" in your case) and type you ask hibernate to get session.get(type, id);.

In my case error was identifier of an instance of <skipped> was altered from 16 to 32.
Object's PK type was Integer, hibernate was asked for Long type.

不甘平庸 2024-10-09 05:35:52

就我而言,这是因为该属性在对象上很长,但在映射 xml 中是 int,这个异常应该更清楚

In my case it was because the property was long on object but int in the mapping xml, this exception should be clearer

偷得浮生 2024-10-09 05:35:52

如果您使用 Spring MVC 或 Spring Boot 尽量避免:
@ModelAttribute("user") 在一个控制器中,以及在另一个控制器中
model.addAttribute("user", userRepository.findOne(someId);

这种情况会产生这样的错误。

If you are using Spring MVC or Spring Boot try to avoid:
@ModelAttribute("user") in one controoler, and in other controller
model.addAttribute("user", userRepository.findOne(someId);

This situation can produce such error.

作死小能手 2024-10-09 05:35:52

这是一个老问题,但我将添加针对我的特定问题(Spring Boot、JPA using Hibernate、SQL Server 2014)的修复,因为它与此处包含的其他答案不完全匹配:

我有一个外键,例如 my_id = '12345',但引用列中的值为 my_id = '12345 '。它的末尾有一个 额外的空格,这是 hibernate 不喜欢的。我删除了该空间,修复了允许此额外空间的代码部分,一切正常。

This is an old question, but I'm going to add the fix for my particular issue (Spring Boot, JPA using Hibernate, SQL Server 2014) since it doesn't exactly match the other answers included here:

I had a foreign key, e.g. my_id = '12345', but the value in the referenced column was my_id = '12345 '. It had an extra space at the end which hibernate didn't like. I removed the space, fixed the part of my code that was allowing this extra space, and everything works fine.

眼眸印温柔 2024-10-09 05:35:52

面临同样的问题。
我在两颗豆子之间建立了联系。在bean AI中将变量类型定义为Integer,在bean BI中将相同的变量定义为Long。
我将它们都更改为整数。这解决了我的问题。

Faced the same Issue.
I had an assosciation between 2 beans. In bean A I had defined the variable type as Integer and in bean B I had defined the same variable as Long.
I changed both of them to Integer. This solved my issue.

电影里的梦 2024-10-09 05:35:52

我通过实例化依赖对象的新实例来解决这个问题。举个例子

instanceA.setInstanceB(new InstanceB());
instanceA.setInstanceB(YOUR NEW VALUE);

I solve this by instancing a new instance of depending Object. For an example

instanceA.setInstanceB(new InstanceB());
instanceA.setInstanceB(YOUR NEW VALUE);
风情万种。 2024-10-09 05:35:52

就我而言,我在数据库中有一个带有重音的主键,但在其他表中其外键没有。由于某种原因,MySQL 允许这样做。

In my case I had a primary key in the database that had an accent, but in other table its foreign key didn't have. For some reason, MySQL allowed this.

难忘№最初的完美 2024-10-09 05:35:52

您似乎更改了实例的标识符
由 JPA 实体上下文管理的 org.cometd.hibernate.User 对象。
在本例中,创建具有适当 id 的新用户实体对象。并设置它来代替原来的 User 对象。

It looks like you have changed identifier of an instance
of org.cometd.hibernate.User object menaged by JPA entity context.
In this case create the new User entity object with appropriate id. And set it instead of the original User object.

2024-10-09 05:35:52

您是否使用来自同一服务类的多个事务管理器。
例如,如果您的项目有两个或多个事务配置。
如果属实的话,
然后首先将它们分开。

Did you using multiple Transaction managers from the same service class.
Like, if your project has two or more transaction configurations.
If true,
then at first separate them.

書生途 2024-10-09 05:35:52

我遇到了问题,

session.save(entity)

当我尝试获取现有的数据库实体,修改了一些字段并执行时,

session.merge(entity)

因为它存在于数据库中,所以我们应该 merge() 而不是 save()< /强>

I got the issue when i tried fetching an existing DB entity, modified few fields and executed

session.save(entity)

instead of

session.merge(entity)

Since it is existing in the DB, when we should merge() instead of save()

蘸点软妹酱 2024-10-09 05:35:52

您可能会修改所获取实体的主键,然后尝试使用同一事务进行保存以从现有记录创建新记录。

you may be modified primary key of fetched entity and then trying to save with a same transaction to create new record from existing.

私野 2024-10-09 05:35:52

我遇到了同样的问题

"message": "identifier of an instance of com.intern.assignment.model.Event was altered from 0 to 2"

,然后我检查了我的 EventController.java 并在该控制器中错误地尝试像其他属性一样更新“eventId”(主键属性)。然后我评论了一下,然后再试一次。哇,问题消失了。

//update event
@PutMapping("/eventsUpdate/{id}")
public ResponseEntity<Event> updateEvent(@PathVariable(value = "id") Long eventId, @Validated @RequestBody Event eventDetails) throws ResourceNotFoundException{
    
    Event event = eventRepository.findById(eventId).orElseThrow(() -> new ResourceNotFoundException("Event not found for this id: " + eventId));
    
    event.setAddrNbr(eventDetails.getAddrNbr());
    event.setClientId(eventDetails.getClientId());
    event.setEventCnt(eventDetails.getEventCnt());
    //event.setEventId(eventDetails.getEventId());
    event.setLocationCd(eventDetails.getLocationCd());
    event.setLocationId1(eventDetails.getLocationId1());
    event.setLocationId2(eventDetails.getLocationId2());
    event.setRcNum(eventDetails.getRcNum());
    event.setTransId(eventDetails.getTransId());
    event.setTransTms(eventDetails.getTransTms());
    return ResponseEntity.ok(this.eventRepository.save(event));
    
}

I got the same issue

"message": "identifier of an instance of com.intern.assignment.model.Event was altered from 0 to 2"

then I checked my EventController.java and in that Controller mistakenly I tried to update 'eventId'(Primary Key Attribute) like other attribures. Then I commented it and try it again. Wow, issue was gone.

//update event
@PutMapping("/eventsUpdate/{id}")
public ResponseEntity<Event> updateEvent(@PathVariable(value = "id") Long eventId, @Validated @RequestBody Event eventDetails) throws ResourceNotFoundException{
    
    Event event = eventRepository.findById(eventId).orElseThrow(() -> new ResourceNotFoundException("Event not found for this id: " + eventId));
    
    event.setAddrNbr(eventDetails.getAddrNbr());
    event.setClientId(eventDetails.getClientId());
    event.setEventCnt(eventDetails.getEventCnt());
    //event.setEventId(eventDetails.getEventId());
    event.setLocationCd(eventDetails.getLocationCd());
    event.setLocationId1(eventDetails.getLocationId1());
    event.setLocationId2(eventDetails.getLocationId2());
    event.setRcNum(eventDetails.getRcNum());
    event.setTransId(eventDetails.getTransId());
    event.setTransTms(eventDetails.getTransTms());
    return ResponseEntity.ok(this.eventRepository.save(event));
    
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文