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?
While the original question has been answered already, I would like to highlight an important point for people who are new with Hibernate as it might help to avoid some confusion.
The javadoc of Hibernate 5.4 of the @Column annotation, says for its optional element Updatable:
(Optional) Whether the column is included in SQL UPDATE statements generated by the persistence provider.
If you issue an update statement with HQL or using CriteriaUpdate, against a field that you have annotated with @Column(updatable = false)
, your update statement will be executed .
The @Column(updatable = false)
works, when you are using either Hibernate’s update
or JPA’s merge
method.
No exception will be thrown (unlike for ex.: @Column(nullable= false)
as it creates a constraint...), but the generated update statement will not include the marked field.
For further information, it is really a must to familiarise yourself with the JPA’s entity lifecycle states and the methods that manages them, as can be seen on the picture below.
As well as I highly recommend to read this article which explains this in details, and is the source of the attached picture.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With