![](/img/trans.png)
[英]LazyInitializationException with ModelMapper (Spring + Hibernate)
[英]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.