Spring Data 2.0.x AuditorAware getCurrentUser方法抛出AbstractMethodError

时间:2018-02-28 06:55:47

标签: java spring spring-data-jpa

我正在尝试将AuditorAware实施到我的网络应用程序中。以下是我的图书馆版本列表:

  • jsf 2.2.13
  • hibername 5.1.3.Final
  • spring 5.0.3.RELEASE
  • spring-data 2.0.3.RELEASE
  • spring-security 5.0.1.RELEASE

这是我的持久性配置文件:

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableTransactionManagement
public class PersistenceContext
{
     @Bean
     public AuditorAware<AccountModel> auditorAware()
     {
         return new AuditorAwareImpl();
     }
}

这是我的AuditorAwareImpl类:

public class AuditorAwareImpl implements AuditorAware<AccountModel>
{
    @Override
    public Optional<AccountModel> getCurrentAuditor()
    {
        return Optional.ofNullable((AccountModel) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
    }
}

AccountModel:

@Entity(name = "Account")
@Table(name = "account")
public class AccountModel extends BaseModel implements UserDetails
{
    private static final long serialVersionUID = -4792614546550769652L;

    @Column(name = "username", length = 20, nullable = false)
    private String username;

    @Column(name = "password", length = 100, nullable = false)
    private String password;

    @Column(name = "email", length = 100, nullable = false)
    private String email;

    @Column(name = "accPackage", length = 2, nullable = false)
    private String accPackage;

    @OneToMany(mappedBy = "account", cascade = CascadeType.ALL)
    private Set<RoleModel> role = new HashSet<RoleModel>();

    @Transient
    private transient Set<GrantedAuthority> authorities;
}

BaseModel:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseModel implements Serializable
{
    private static final long serialVersionUID = -8027746305948051121L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private Integer id;

    @CreatedBy
    @ManyToOne
    @JoinColumn(name = "createdBy", nullable = true, updatable = false)
    private AccountModel createdBy;

    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "dateCreated", nullable = false, updatable = false)
    private Date dateCreated;

    @LastModifiedBy
    @ManyToOne
    @JoinColumn(name = "modifiedBy", insertable = false)
    private AccountModel modifiedBy;

    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "dateModified", insertable = false)
    private Date dateModified;

    @Version
    @Column(name = "verCtrl", nullable = false)
    private Integer version;
}

当我尝试持久化对象时,将抛出AbstractMethodError:

Caused by: java.lang.AbstractMethodError: com.project.core.AuditorAwareImpl.getCurrentAuditor()Ljava/lang/Object;
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy71.getCurrentAuditor(Unknown Source)
    at org.springframework.data.auditing.AuditingHandler.touchAuditor(AuditingHandler.java:166)
    at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:145)
    at org.springframework.data.auditing.AuditingHandler.markCreated(AuditingHandler.java:125)
    at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForCreate(AuditingEntityListener.java:83)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.hibernate.jpa.event.internal.jpa.ListenerCallback.performCallback(ListenerCallback.java:35)
    ... 124 more


更新

在我将Spring数据从2.x更改为1.x后,它可以工作,不再是例外。我认为问题在于getCurrentUser()方法的返回数据类型。在1.x中,返回数据类型只是您的自定义UserDetails对象,但在2.x中,返回数据类型为Optional<CustomModel>。可能是错误的原因吗?

1 个答案:

答案 0 :(得分:3)

是的,此错误的原因是getCurrentUser()方法的返回数据类型更改。 在2.x版本中,此选项更改为Optional(在1.x版本中,返回类型仅为T)。 有两种解决方法:

  1. 将Spring数据从2.x降级到1.x
  2. 但是,由于我必须将Spring Data保持在2.x版本上,所以我只是将代码从更改为

    @Override public String getCurrentAuditor() { return currentUser(); }

@Override public Optional<String> getCurrentAuditor() { return Optional.of(currentUser()); }