在没有 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,它就开始正常工作了。
我有一个基于 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,它就开始正常工作了。