87
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?

3
  • Your user table must change its value? Which value? The user table presumably contains several rows with several values each ...
    – meriton
    Commented Nov 14, 2010 at 20:20
  • from [number] to 0 for me occurred when i save live object instead of update. Commented Oct 5, 2020 at 13:01
  • Try to change the property name of db column in your model. I have similar problem, and i solve the problem in this answer stackoverflow.com/a/66395423/15293948
    – neuer
    Commented Feb 27, 2021 at 3:58

23 Answers 23

65

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?

2
  • Hi Juha, you are absolutely correct, I assign primary key to User object. Thanks a lot for your help!
    – gennad
    Commented Nov 15, 2010 at 4:55
  • 12
    I had somewhat to some issue. My error message contained .. was altered from 1 to 1 .. My primairy key was set to long in my entity class but was mapped to int in my mapping file. Commented Feb 8, 2012 at 7:46
38

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

1
17

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

2
  • Thanks, that's exactly what I had (but then Int32 instead of Int64). Commented Nov 14, 2012 at 13:42
  • I had a similar issue in Lucee 5: the PK in one table was type='numeric' but the same field in a composite key in another table did not have that. Adding type='numeric' to the field in the composite key fixed the error. Commented Apr 17, 2018 at 13:54
6

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

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.

5

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.

5

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

4

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);
}
2
  • Thanks! This was a very useful answer as I couldn't get detaching working and this answer gave me the idea to use a new object and copy the properties in using BeanUtils.copyProperties(). Commented Aug 1, 2016 at 19:59
  • This helped with my batch operation. I was using the same object without initializing.
    – Geek
    Commented Sep 17, 2020 at 21:15
4

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);
}  
1
  • Have the same issue, using something like userDB.setLocation(new Location()); worked, also, if i remove the @Transactional also works. Commented Sep 2, 2020 at 17:44
3

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!

2

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.

1

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.

0

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

0

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.

0

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.

0

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.

0

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

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

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.

0

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.

0

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.

0

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

0

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

0

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.