【问题标题】:LazyInitializationException Spring and HibernateLazyInitializationException Spring 和 Hibernate
【发布时间】:2015-03-06 09:37:56
【问题描述】:

我得到这个异常嵌套异常是org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ibm.ro.model.Location.subLocations, could not initialize proxy - no Session.

我在访问集合时确实知道,事务已经关闭,这就是代码抛出此异常的原因。这是我的示例代码

@Entity
@Table(name="location")
public class Location extends BaseEntity {

    private static final long serialVersionUID = 1L;

    private String name;
    private List<Location> subLocations;
    private Location location;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "location")
    public List<Location> getSubLocations() {
        return subLocations;
    }
    public void setSubLocations(List<Location> subLocations) {
        this.subLocations = subLocations;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    public Location getLocation() {
        return location;
    }
    public void setLocation(Location location) {
        this.location = location;
    }

    @Override
    public String toString() {
        return "Location [name=" + name + ", subLocations=" + subLocations
            + "]";
    }

}

这是我的 DAO:

@Repository("locationDao")
public class LocationDao implements ILocationDao{

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public List<Location> getAll() {
        Session sess = getSession();
        return sess.createCriteria(Location.class).setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY).list();
    }
}

那么这是我的服务:

@Service("locationService")
@Transactional
public class LocationService implements ILocationService{

    @Autowired
    ILocationDao dao;

    @Override
    public List<Location> getAll() {
        return dao.getAll();
    }
}

这是抛出异常的控制器:

@Controller
public class BaseController {

    @Autowired
    ILocationService service;

    private static final String VIEW_INDEX = "index";
    private final static org.slf4j.Logger logger =    LoggerFactory.getLogger(BaseController.class);

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String location(ModelMap model) {        
    logger.debug(service.getAll().toString());
        return VIEW_INDEX;
    }
}

在不使用 OpenSessionInViewFilter 的情况下如何解决问题?

【问题讨论】:

  • 您可以通过更改实体来急切地获取它们

标签: spring hibernate lazy-initialization


【解决方案1】:

你可以在你的服务中迭代你的位置(你仍然有你的事务)并在元素上调用Hibernate.initialize,强制初始化持久集合。

    @Override
    public List<Location> getAll() {
        List<Location> locations = dao.getAll();
        for (Location location : locations ) { 
          Hibernate.intialize(location.getSubLocations())
        }
        return locations;
    }

【讨论】:

  • 他有@Transactional,他不需要显式调用Hibernate.intialize,在他的服务中调用location.getSubLocations()就足够了,并且会初始化子位置。
  • true,尽管他必须调用 location.getSubLocations().size() 或任何其他方法。但是 Hibernate.initialize 是一种专用方法,可以让您避免这种情况。它明确地标记了仅初始化的目的。否则,如果它是 JPA,我会求助于你提到的,但我知道 OP 直接使用 Hibernate,在这种情况下,我会使用 Hibernate.initialize,这是我的经验法则
  • 我知道这是 HIbernate 的最佳实践。然而,依赖 ORM 提供服务并不是一个好主意,恕我直言。如果明天你改变主意并停止使用休眠怎么办?所以最好保持它尽可能干净,不要依赖于 ORM 特定的方法。
  • 是的,虽然这个考虑需要设置在更高的级别,所以直接选择 JPA/Hibernate 而不是 Hibernate。如果您查看发布的代码 sn-ps,您会看到如果换出休眠模式,则需要更改更多更改。所以就个人而言,如果它只是休眠,我会只使用专用的 Hibernate.initialize 进行初始化,另一方面,我个人总是努力针对 JPA 接口进行开发。好话,也许你会用 OP 激发更多概念性的重新设计
  • 您好主从,我尝试使用您的答案,它在 getAll() 上完美运行。但奇怪的是,我还有另一个方法 getRegions() 仍然会引发延迟初始化异常。我复制并粘贴了相同的代码块,仅将 getAll() 更改为 getRegions()。任何想法为什么会这样?提前致谢。
猜你喜欢
  • 2012-12-28
  • 1970-01-01
  • 2011-12-21
  • 1970-01-01
  • 2017-02-23
  • 2012-11-19
  • 1970-01-01
  • 2014-07-11
相关资源
最近更新 更多