在没有 OpenEntityManagerInViewFilter 的情况下从 JPA2 存储库中获取惰性实体失败

Fetching lazy entities from JPA2 repository fails without OpenEntityManagerInViewFilter

我有一个基于 java 的配置,我在其中定义了与数据库相关的 bean,如下所示:

@Configuration
@EnableJpaRepositories("z.y.x")
@EnableTransactionManagement(mode = AdviceMode.PROXY)
public class DatabaseConfig {

    @Autowired
    DataSource dataSource;

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource);
        bean.setPackagesToScan("z.y.x");
        bean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        bean.setJpaPropertyMap(getJpaProperties());
        return bean;
    }

    private Map<String, Object> getJpaProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("hibernate.hbm2ddl.auto", "validate");
        map.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        map.put("hibernate.show_sql", false);
        map.put("hibernate.format_sql", true);
        map.put("hibernate.use_sql_comments", true);
        return map;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    @Bean
    public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

然后在我的服务中,我从数据库中获取一些数据

@Override
@Transactional
public UserDTO getUserByUsername(String username) {
    User user = userRepo.getUserByUsername(username);
    return userConverter.convert(user);
}

用户对象具有这种结构

@Entity
@Table(name = "USERS", uniqueConstraints =
@UniqueConstraint(columnNames = {"username"}))
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private int id;

    private String username;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = {CascadeType.ALL}, orphanRemoval = true)
    private Set<AccessLevel> accesses = new HashSet<>(0);

所以请注意它有 accesses 惰性 属性,userConverter 想在 getUserByUsername 事务方法中转换为 DTO。但是,当它发生时,它会失败并出现此错误

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: repositories.models.User.accesses, could not initialize proxy - no Session

我不知道为什么会这样。

这可以通过将以下过滤器添加到 web.xml 来解决:

<filter>
    <filter-name>oemInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
        <param-value>entityManagerFactory</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>oemInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

但是,这似乎是一个错误的修复。我想为我的问题找到合适的解决方案。

在这个问题上花了好几个小时,我终于弄明白了。我有一个定义了 @ComponentScan 的 ApplicationConfig class,它又加载了 DatabaseConfig 文件。因此,一旦我将 @EnableJpaRepositories("z.y.x")@EnableTransactionManagement(mode = AdviceMode.PROXY) 注释移动到 ApplicationConfig class,它就开始正常工作了。