【问题标题】:Obtaining Hibernate Session with Spring JPA使用 Spring JPA 获取休眠会话
【发布时间】:2015-09-12 19:10:30
【问题描述】:

我似乎无法让我的 Spring JPA 配置正常工作。我有一个 Spring REST 服务。如果我将所有实体设置为 FetchType.EAGER,一切都会按预期进行。但出于显而易见的原因,我不想这样做。

当我将实体设置为 FetchType.LAZY 时,我收到以下错误:

org.hibernate.LazyInitializationException: 延迟初始化失败 角色集合:com.service.entities.MyEntity.lawfirmCaseDecisions, 无法初始化代理 - 没有会话

我查看了其他类似的 SO 问题,但我仍然遇到同样的问题。这是我的配置:

@Configuration
@Import(EnvironmentProvider.class)
@EnableTransactionManagement
@Slf4j
public class DataSourceProvider {

    @Autowired EnvironmentProvider envProvider;

    @Bean
    DataSource dataSource() {

        final EnvConfig env = envProvider.envConfig();

        MysqlDataSource dataSource = new MysqlDataSource();    
        dataSource.setUrl(env.findProperty("db.url"));
        dataSource.setPortNumber( Integer.parseInt(env.findProperty("db.port")) );
        dataSource.setUser(env.findProperty("db.username"));
        dataSource.setPassword(env.findProperty("db.password"));
        return dataSource;
    }

    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource());
        entityManagerFactoryBean.setPackagesToScan("com.offtherecord.service.core.entities");
        //entityManagerFactoryBean.setPersistenceUnitName("OTR");   

        HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
        entityManagerFactoryBean.setJpaVendorAdapter(va);

        Properties ps = new Properties();
        ps.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        // ps.put("hibernate.show_sql", "true"); //useful for debugging
        ps.put("hibernate.format_sql", "true");

        entityManagerFactoryBean.setJpaProperties(ps);
        return entityManagerFactoryBean;
    }

    @Bean
    @PersistenceContext
    JpaTransactionManager transactionManager() {

        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().nativeEntityManagerFactory);
        return transactionManager;
    }
}

为了快速测试,我在控制器方法上添加了@Transactional 注释。在下面的代码中,UserEntity 类有一个未填充的订单列表:

@RequestMapping(method = RequestMethod.GET)
@Transactional
public ResponseEntity<GetOrdersResponse> getOrders() {

    UserEntity activeUser = controllerUtil.getActiveUser();
    ...
    return new ResponseEntity<>(new GetOrdersResponse(), HttpStatus.OK);
}

我很想克服这个问题!

【问题讨论】:

  • 除非您明确调用userEntity.getOrders(),否则不会填充订单。如果还没有,您可以添加此方法调用并查看它的工作原理吗?

标签: java spring hibernate spring-data


【解决方案1】:

你需要使用referenced from here.这样的方法

    @Entity
@NamedEntityGraph(name = "GroupInfo.detail",
  attributeNodes = @NamedAttributeNode("members"))
public class GroupInfo {

  // default fetch mode is lazy.
  @ManyToMany
  List<GroupMember> members = new ArrayList<GroupMember>();

  …
}

示例 48. 在存储库查询方法上引用命名实体图定义。

@Repository
public interface GroupRepository extends CrudRepository<GroupInfo, String> {

  @EntityGraph(value = "GroupInfo.detail", type = EntityGraphType.LOAD)
  GroupInfo getByGroupName(String name);

}

在上面的这个例子中,你需要在你想要加载特定关联的特定方法中标记成员。在上面的例子中,它是“members”字段。

一般来说,所有的关联都被标记为惰性,并且可以根据需要获取您想要获取的关联,可以创建这样的特殊方法。例如,假设您有一个屏幕,其中包含客户的所有详细信息,因此在这样的 VIEW 中,您将有一个自定义方法,它可以急切地加载客户的所有地址,而对于其他视图,这些地址可以保持惰性并且可以急切地加载其他内容。

确实有效, 谢谢。

【讨论】:

    猜你喜欢
    • 2013-07-26
    • 2014-08-14
    • 1970-01-01
    • 2013-12-19
    • 2012-07-30
    • 2020-11-13
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多