2014-12-17 14 views
5

NOTA: Questa è una domanda complicata, quindi spero di aver coperto le parti pertinenti. In caso contrario, modifico e aggiungo ulteriori informazioni come richiesto.Spring L'entità controllabile viene modificata anche quando nulla è cambiato

Stiamo usando Spring (4.1.0) con Hibernate (4.3.6) e abbiamo definito una classe base che tutte le nostre entità si estendono chiamate BaseAuditableEntity (codice di seguito). Quando un'entità viene caricata in un metodo @Transactional e successivamente modificata e salvata, l'entità modified_by_user_id e modified_ts vengono entrambe aggiornate con l'id dell'utente che ha effettuato l'accesso eseguendo qualsiasi modifica venga apportata.

nostro problema è che ogni volta che un AppUser (che si estende anche BaseAuditableEntity) viene caricato in uno di questi metodi @Transactional, è anche vedendo la modified_by_user_id e modified_ts stato impostato anche se non è stato modificato. Questo crea un problema perché stiamo scrivendo alla nostra tabella utenti con quasi tutte le richieste quando non è necessario. Notare che ciò può anche influire sui metodi @Transactional che non caricano esplicitamente lo AppUser poiché lo AuditorBean carica uno stesso AppUser.

Suppongo che questo abbia qualcosa a che fare con il fatto che l'entità AppUser è parte della BaseAuditableEntity stessa. Qualcuno può confermarlo? c'è un modo per risolvere questo problema?

nostra BaseAuditableEntity classe che ogni entità tra cui appuser estende:

@MappedSuperclass 
@EntityListeners(AuditingEntityListener.class) 
public abstract class BaseAuditableEntity implements Auditable<AppUser, Long> { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hibernate_sequence") 
    @SequenceGenerator(name = "hibernate_sequence", sequenceName = "blah_sequence", allocationSize = 1) 
    @Column(name = "id") 
    private Long id; 

    @CreatedBy 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "created_by_user_id") 
    private AppUser createdBy; 

    @LastModifiedBy 
    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "modified_by_user_id") 
    private AppUser lastModifiedBy; 

    @Column(name = "created_ts") 
    @CreatedDate 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date createdDate; 

    @Column(name = "modified_ts") 
    @LastModifiedDate 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date lastModifiedDate; 

    // ... 
} 

nostro JpaConfig:

@Configuration 
@EnableJpaRepositories(basePackages = { 
     "blah.blah.blah"}) 
@ComponentScan(basePackageClasses = {AuditorBean.class}) 
@EnableTransactionManagement 
@EnableJpaAuditing(auditorAwareRef = "auditorBean") 
public class JpaConfig extends BaseConfig { 

    // ... 

} 

E la nostra AuditorBean:

@Component 
public class AuditorBean implements AuditorAware<AppUser> { 

    @Override 
    public AppUser getCurrentAuditor() { 
     // omitting some code that finds a user. I think the only relevant thing here 
     // is that we're using the repo to find the user by ID and not using an 
     // entity that's already been loaded 
     return userRepository.findOne(id); 
    } 

} 

risposta

0

Il mio suggerimento è quello di mantenere controllo semplice anddefine

@CreatedBy 
private Long createdBy; 

senza associazione effettiva e memorizzare solo l'ID di AppUser.

@Component public class AuditorBean implementa AuditorAware {

@Override 
public Long getCurrentAuditor() { 
    // .... find out the id 
    return id; 
} 

}

Problemi correlati