2014-12-15 8 views
6

Sto usando Spring Data JPA con Hibernate e sto avendo problemi con la proprietà updatable = false sull'annotazione @Column.Hibernate aggiornabile = falso Il campo UUID è aggiornato

Ho una classe di base per tutti i miei @Entity oggetti con un UUID definita in questo modo:

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

} 

Annotare la updatable = false annotazione.

Per verificare il campo UUID in realtà non è aggiornabile, ho scritto questo 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()); 
} 

mi è stato effettivamente aspettavo un'eccezione per essere gettato sulla chiamata alla userRepo.save(user), ma che ciò non accada. Invece, l'ultimo assertEquals() fallisce, il che significa che l'UUID si stava effettivamente aggiornando.

È questo comportamento previsto? C'è un modo per impedire la modifica degli UUID?

+0

Non è l'aggiornamento, il test è viziata. Non ci saranno eccezioni, il campo verrà ignorato silenziosamente quando si salva/aggiorna l'oggetto. Nulla è cambiato nel database. Il problema con il tuo test è che tutto accade in una singola transazione e quindi un'unica cache di primo livello (cioè "EntityManager"). L'oggetto 'user' e' user2' sono lo stesso oggetto ('user == user2' dovrebbe restituire' true'). La tua ultima asserzione è falsa quando hai cambiato la rappresentazione in memoria dell'oggetto 'User'. Non quello del database. Si desidera utilizzare una query semplice per verificarlo. –

risposta

5

Come da documentation, la proprietà updatable ha deciso se la colonna sarebbe stata parte dell'istruzione di aggiornamento. Significa che Hibernate lo ignora quando invia gli aggiornamenti al database. Pertanto, lo stato in memoria e lo stato del database saranno diversi.

Per verificare questo, prova a cancellare la sessione (sfrattare) prima di chiamare User user2 = userRepo.findOne(1L)

+0

Conoscevo la prima parte, ma non avevo realizzato che Hibernate stava memorizzando l'oggetto nella cache. Ho aggiunto 'entityManager.clear();' prima di 'findOne()' nel mio test e ora passa con precisione. Grazie per aver suggerito il diritto direttamente. – JBCP

Problemi correlati