繁体   English   中英

休眠-LazyInitializationException

[英]Hibernate - LazyInitializationException

我有一个简单的代码。 我在数据库中添加了一些播放器,在这里我想在第一个播放器中设置昵称:

private void mod() {
    Player p = playersService.loadById(1L);
    p.setNick("OtherNick");
}

它给出: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

PlayersService.load():

@Transactional
public Player loadById(Long id) {
    return playersDao.load(id);
}

PlayersDao.load()-从AbstractDao扩展:

@SuppressWarnings("unchecked")
public T load(Serializable id) {
    return (T) currentSession().load(getDomainClass(), id);
}

我在这里还有一个问题: @Transactional应该在DAO层还是Service层?

休眠配置:

// package declaration and import statements

@Configuration
@ComponentScan(basePackages = { "eniupage" }, excludeFilters = {
        @Filter(type = FilterType.ANNOTATION, value = EnableWebMvc.class) })
@EnableTransactionManagement
public class RootConfig {
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName( "com.mysql.jdbc.Driver" );
        dataSource.setUrl( "jdbc:mysql://localhost:3306/eniupage" );
        dataSource.setUsername( "eniupage" );
        dataSource.setPassword( "qwer1234" );
        return dataSource;
    }

    @Autowired
    @Bean
    public LocalSessionFactoryBean sessionFactory( DataSource dataSource ) {
        LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
        sfb.setDataSource( dataSource );
        sfb.setPackagesToScan( new String[] { "eniupage.domain"} );
        Properties props = new Properties();
        props.setProperty( "hibernate.dialect", "org.hibernate.dialect.MySQLDialect" );
        props.setProperty( "hibernate.hbm2ddl.auto", "create-drop" );
        props.setProperty( "hibernate.show_sql", "true" );

        sfb.setHibernateProperties( props );
        return sfb;
    }



    @Bean
    public BeanPostProcessor persistenceTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    @Autowired
    @Bean(name = "transactionManager")
    public HibernateTransactionManager getTransactionManager(
            SessionFactory sessionFactory) {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager(
                sessionFactory);

        return transactionManager;
    }
}

Hibernate中的load方法可能返回一个代理,而不是实际对象。 然后,当在Hibernate会话仍处于打开状态时访问持久属性之一时,代理将加载实体状态。

在您的情况下,Hibernate会话绑定到由于存在@Transactional而创建的事务。 事务完成后,将在加载代理之前关闭会话。 将以下方法更改为使用始终获取实体状态的get方法。 NB get方法如果在数据库中找不到提供的键的行,则返回null

return (T) currentSession().load(getDomainClass(), id);

return (T) currentSession().get(getDomainClass(), id);

注意:您的mod()方法t result in the player数据库中更新t result in the player的昵称。 没有活动的会话可以监视更改并刷新到数据库。 播放器实体处于分离状态且不受管理。您需要将播放器合并到活动会话中

例如

private void mod() {
    Player p = playersService.loadById(1L);
    p.setNick("OtherNick");
    playerService.updatePlayer(p);
}

Then in PlayerService

@Transactional
public void updatePlayer(Player player){
   session.merge(player);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM