2014-12-17 7 views
5

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

} 

Antwort

0

Mein Vorschlag ist, zu halten Audit

@CreatedBy 
private Long createdBy; 

ohne tatsächliche Zuordnung und speichern Sie dort nur AppUsers ID.

@Component public class AuditorBean implementiert AuditorAware {

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

}

Verwandte Themen