0

I have a simple code. I added some players to database and here I want to set nick in first player:

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

It gives: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

PlayersService.load():

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

PlayersDao.load() - extended from AbstractDao:

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

I have here one more question: @Transactional should be in DAO layer or Service layer?

Hibernate Config:

// 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;
    }
}
1

1 Answer 1

0

The load method in Hibernate may return a proxy and not the real object. The proxy will then load the entity state when one of the persistent properties is accessed whilst the Hibernate session is still open.

In your case the Hibernate session is bound to the transaction created due to the presence of @Transactional. When the transaction is completed the session is closed before the proxy has loaded. Change the following method to use get method which always fetches the entity state. N.B get method returns null if no row is found in the database for the provided key

Change from

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

to

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

N.B Your mod() method wont result in the players nickname being updated in the database. There is no session which is active to monitor the changes and flush to the database. The player entity is in a detached state and is not managed You need to merge the player into an active session

For example

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);
}
Sign up to request clarification or add additional context in comments.

4 Comments

No exceptions but it doesn't change the nick
It wont change the nickname before there is no session which is active to monitor the changes and flush them to the database.I am updating the answer to reflect that
But .. why when I removed mod() from controller and put it to service layer it works without updating ?
The transaction propagates and ends after method mod().Hence the session is still open and the entity is managed

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.