首页 > 解决方案 > 无法为实现 Spring Security UserDetails 的类加载请求的类异常

问题描述

我使用 aLocalContainerEntityManagerFactoryBean来设置 JPA EntityManagerFactory。在我扫描的扫描实体中,setPackagesToScan我有一个实现 spring security interface 的 User 实体UserDetails

当我午餐我的应用程序我有这个错误:

Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [com.medkhelifi.model.entities.User]
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:354)
    at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.<init>(AnnotationMetadataSourceProcessorImpl.java:105)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.<init>(MetadataBuildingProcess.java:156)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:150)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758)
    ... 11 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : com.medkhelifi.model.entities.User
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl$AggregatedClassLoader.findClass(ClassLoaderServiceImpl.java:342)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:351)
    ... 23 more

这就是我配置我的应用程序的方式:**Beans config:**

@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan("com.medkhrlifi.tutorials.designpatterns.dao")
@EnableTransactionManagement
public class AppConfig {
    // properties variable goes here ...    

    @Bean
    public DataSource dataSource(){
        // datasource config goes here ...
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean lem = new LocalContainerEntityManagerFactoryBean();
        lem.setDataSource(dataSource());
        lem.setJpaVendorAdapter(vendorAdapter);
        lem.setPackagesToScan("com.medkhelifi.model.entities");
        lem.setJpaProperties(jpaProperties());
        //lem.afterPropertiesSet();
        return lem;
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager(){
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
        return txManager;
    }

    @Bean
    public Properties jpaProperties(){
        Properties jpa = new Properties();
        jpa.put("hibernate.dialect", dialect);
        return jpa;
    }
}

用户实体

@Data
@Entity
@Table(name = "user")
public class User implements UserDetails {
    private static final Logger logger = LoggerFactory.getLogger(User.class);

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private String id;

    @NotEmpty
    private String firstname;

    @NotEmpty
    private String lastname;

    @NotEmpty
    private String email;

    @NotEmpty
    private String password;


    //@ElementCollection(fetch = FetchType.EAGER)
    //@Builder.Default
    @DBRef
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_role",
            joinColumns = @JoinColumn(name = "id_user"),
            inverseJoinColumns = @JoinColumn(name = "id_role"))
    private List<Role> roles = new ArrayList<>();

    // Override methods goes here
}

** 更新 ** 我知道错误来自 UserDetails 接口实现,因为如果我删除它,我的应用程序将正常启动,但这不是我想要的。

这就是我运行我的应用程序的方式(仅用于测试目的):

public class DaoApp {

    private static AnnotationConfigApplicationContext applicationContext=  new AnnotationConfigApplicationContext (AppConfig.class);

    public static void main(String[] args) throws ParseException {
        System.out.println("main app for test purpose only started successfully");  
    }
}

我希望我已经提供了足够的信息来提供帮助。

标签: javaspringjpaspring-security

解决方案


UserDetails我通过从我的实体中删除接口的实现绕过了这个问题User,并设置了一个新机制来恢复GrantedAuthoritySpring Security 所必需的。但是我仍然不明白为什么这个接口实现setPackagesToScan会导致 JPA 使用的问题EntityManagerFactory

如果有人可以给我们一个解释?


推荐阅读