Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 405
JBCP Avatar asked Dec 15 '14 16:12

JBCP


1 Answers

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.

JPA’s entity lifecycle states

like image 186
Z3d4s Avatar answered Sep 22 '22 05:09

Z3d4s