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);
}
}