HINWEIS: Dies ist eine komplizierte Frage, also hoffe ich, dass ich die relevanten Teile behandelt habe. Wenn nicht, werde ich bearbeiten und weitere Informationen hinzufügen, wie gewünscht.Spring Audible Entity wird geändert, auch wenn sich nichts geändert hat
Wir verwenden Spring (4.1.0) mit Hibernate (4.3.6) und haben eine Basisklasse definiert, die alle unsere Entitäten BaseAuditableEntity
(Code unten) heißt. Wenn eine Entität in eine @ Transactional-Methode geladen und anschließend geändert und gespeichert wird, werden die Entitäten und modified_ts
beide mit der ID des angemeldeten Benutzers aktualisiert und führen die Änderungen aus, die vorgenommen werden.
Unser Problem ist, dass, wenn ein AppUser
(die auch BaseAuditableEntity erstreckt) in einer dieser @Transactional
Methoden geladen, es ist auch die modified_by_user_id
und die modified_ts
sehen gesetzt werden, auch wenn es nicht geändert wurde. Dies führt zu einem Problem, da wir mit fast jeder Anfrage in unsere Benutzertabelle schreiben, wenn dies nicht erforderlich ist. Beachten Sie, dass dies auch Auswirkungen auf @Transactional
Methoden haben kann, die die AppUser
nicht explizit laden, da die AuditorBean
eine AppUser
lädt.
Ich nehme an, dies hat etwas damit zu tun, dass die AppUser-Entität Teil der BaseAuditableEntity selbst ist. Kann das jemand bestätigen? Gibt es eine Möglichkeit, dieses Problem zu lösen?
Unsere BaseAuditableEntity
Klasse, die jede Entität einschließlich AppUser erweitert:
@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;
// ...
}
Unsere JpaConfig
:
@Configuration
@EnableJpaRepositories(basePackages = {
"blah.blah.blah"})
@ComponentScan(basePackageClasses = {AuditorBean.class})
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "auditorBean")
public class JpaConfig extends BaseConfig {
// ...
}
Und unsere AuditorBean
: simple undDefinieren
@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);
}
}