Spring / Hibernate中的链式DAO方法用于惰性初始化

时间:2015-04-08 14:37:41

标签: java spring hibernate dao lazy-initialization

我有一些彼此关系的模型类(UserGroupMessage等)。由于很多原因(我没有提供详细信息,但这不是一个灵活的决定)关系是懒惰,我希望它们保持懒惰。

有时我想加载一些类集合。体育user.getGroups()user.getMessages()但是,由于延迟加载,我需要在DAO类的方法中调用Hibernate.initialize(),这对我来说没问题。

问题是,是否有策略避免声明许多DAO方法加载多个集合组合,重用这些方法?

以下是我想避免的内容的示例:

UserController中

public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/user/view/{id}", method = RequestMethod.GET)
    public String view(@PathVariable Long id, Model model) {
        // Choose one between the following, depending on the case
        User user = userService.getUser(id);
        User user = userService.getUserWithGroups(id);
        User user = userService.getUserWithGroupsAndMessages(id);
        //...
    }
}

UserDAOImpl

@Repository
public class UserDAOImpl implements UserDAO {
    @Override
    public User getUser(long id) {
        return (User) this.getCurrentSession().get(User.class, id);
    }

    @Override
    public User getUserWithGroups(long id) {
        User user = (User) this.getCurrentSession().get(User.class, id);
        Hibernate.initialize(user.getGroups());
        return user;
    }

    @Override
    public User getUserWithGroupsAndMessages(long id) {
        User user = (User) this.getCurrentSession().get(User.class, id);
        Hibernate.initialize(user.getGroups());
        Hibernate.initialize(user.getMessages());
        return user;
    }
}

重点是我想避免为每个案例必须加载的每个集合组合创建多个DAO方法。我希望在Controller中实现类似于User user = userService.getUser(id).initGroups().initMessages();的调用语法,以便在每种情况下仅链接我需要的特定方法。

但在此特定示例中,initXXX()方法将位于模型类User中,该类可能不包含任何@Autowired service,因此不是可能的解决方案。< / p>

有什么想法吗?

- 编辑 -

一些非工作的想法:

选项1。initGroups()模型类中声明User

用户

@Entity
@Table(name="user")
public class User implements Serializable {

    //...

    public User initGroups() {
        Hibernate.initialize(getGroups());
        return this;
    }
}

以这种方式从Controller调用:User user = userService.getUser(id).initGroups();

选项2。initGroups()UserService中声明UserDAO

UserServiceImpl

@Service
@Transactional
public class UserServiceImpl implements UserService {

    //...

    @Override
    public User initGrupos(User user) {
        return userDAO.initGroups(user);
    }
}

在UserDAOImpl

@Repository
public class UserDAOImpl implements UserDAO {

    //...

    @Override
    public User initGroups(User user) {
        Hibernate.initialize(user.getGroups());
        return user;
    }
}

以这种方式从Controller调用:

User user = userService.getUser(id);
user = userService.initGroups(user);

结果(两者都相同):

org.hibernate.HibernateException: collection is not associated with any session
    org.hibernate.collection.internal.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:484)
    org.hibernate.Hibernate.initialize(Hibernate.java:78)
    ...

1 个答案:

答案 0 :(得分:2)

init方法不需要服务,只需要调用Hibernate.initialize,同时保持先前加载对象的Hibernate会话(这是最重要的部分)。