Search code examples
javaspringhibernatejpaspring-data-jpa

Hibernate updatable = false UUID field is updated


I am using Spring Data JPA with Hibernate and am having trouble with the updatable=false property on the @Column annotation.

I have a base class for all of my @Entity objects with a UUID defined like this:

@MappedSuperclass
@Getter @Setter @EqualsAndHashCode(of= {"uuid"})
public abstract class AbstractEntity implements Persistable<Long> {

    @Id
    @GeneratedValue(strategy = AUTO)
    @Column(unique = true, updatable = false)
    private Long id;

    @Column(unique = true, updatable = false)
    private UUID uuid = UUID.randomUUID();

}

Note the updatable = false annotation.

To verify the UUID field is in fact NOT updatable, I have written this test:

@Test
public void testChangeUUID() {

    User user = userRepo.findOne(1L);

    assertNotNull(user);
    assertEquals(USER_UUID, user.getUuid().toString());

    final UUID newUuid = UUID.randomUUID();

    user.setUuid(newUuid);

    user = userRepo.save(user);

    assertEquals(newUuid, user.getUuid());

    User user2 = userRepo.findOne(1L);
    assertNotNull(user2);
    assertEquals("UUID should not have changed", USER_UUID, user2.getUuid().toString());
}

I was actually expecting an exception to be thrown on the call to userRepo.save(user), but that doesn't happen. Instead, the final assertEquals() fails, which means the UUID was in fact updating.

Is this expected behavior? Is there any way to prevent UUIDs from being changed?


Solution

  • As per the documentation, the updatable property decided whether the column would be part of the update statement. It means that Hibernate ignores it when sending updates to the database. Thus, the in-memory state and the database state will differ.

    To verify this, try clearing the session (evict) before calling User user2 = userRepo.findOne(1L)