Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 道、春、冬眠_Java_Hibernate_Spring_Dao - Fatal编程技术网

Java 道、春、冬眠

Java 道、春、冬眠,java,hibernate,spring,dao,Java,Hibernate,Spring,Dao,如果有什么不对劲,请纠正我 现在,当我们使用SpringDAO作为ORM模板时,当我们使用@Transactional属性时, 当在外部而不是在方法内部调用方法时,我们无法控制事务和/或会话 延迟加载节省了资源—减少了对数据库的查询,减少了将所有集合保留在应用程序内存中的内存 因此,如果lazy=false,那么如果一个链接集中有10000条记录,那么所有相关的集合都将被提取,这是无效的 现在,我有一个DAO类中的方法,该方法应该返回一个用户对象。 它具有表示数据库的链接表的集合。 我需要按id

如果有什么不对劲,请纠正我

现在,当我们使用SpringDAO作为ORM模板时,当我们使用@Transactional属性时, 当在外部而不是在方法内部调用方法时,我们无法控制事务和/或会话

延迟加载节省了资源—减少了对数据库的查询,减少了将所有集合保留在应用程序内存中的内存

因此,如果lazy=false,那么如果一个链接集中有10000条记录,那么所有相关的集合都将被提取,这是无效的

现在,我有一个DAO类中的方法,该方法应该返回一个用户对象。 它具有表示数据库的链接表的集合。 我需要按id获取对象,然后查询其集合

当我尝试访问此DAO方法返回的链接集合时,Hibernate会发生“未能延迟初始化集合”异常

请解释一下,这里的解决方法是什么

更新:好吧,我来问你这个问题。DAO是一个抽象层,因此方法“getUserById(Integer id)”应该返回一个对象

如果在某些情况下我需要这些用户对象的链接集合,而在其他情况下我需要这些集合,该怎么办

只有两种方法: 1) 延迟加载=错误 2) 创建不同的方法:getUserByIdWithTheCollections()、getUserByIdWithOtherCollections(),这些方法内部使用您的方法吗

我的意思是只有两种方法,没有更好的吗

更新2:请解释一下,什么会让我明确使用SESSIONFACTORY? 它在实践中看起来如何?我们创建一个DAO对象的实例, 然后将其注入会话工厂,这将意味着 对DAO的方法调用将在同一事务中运行? 在我看来,不管怎样,DAO与使用它的类是分离的


逻辑和事务封装在DAO中,对吗?

您可以在事务中获取链接的集合,以便在您仍在事务中时加载它:

User user = sessionFactory.getCurrentSession().get(User.class, userId);
user.getLinkedCollection().size();
return user;
正如BalusC所指出的,您可以使用
Hibernate.initialize()
而不是
size()
。那要干净得多

然后,当您返回这样一个实体时,惰性字段已经初始化


回复您的PS-在服务级别(而不是DAO)级别上使用事务是否可行?似乎是这样,因为在单独的事务中进行每个DAO调用似乎是一种浪费(可能是不正确的)。

我发现最好将@Transactional放在服务层,而不是DAO层。否则,所有DAO调用都在单独的hibernate会话中—所有这些对象相等的东西都不起作用。

在我看来,解决这个问题的最佳方法是在每个请求的会话模型中设计应用程序。然后,如果您甚至有一个来自DAO的对象,在OSIV模式工作之前,您可以在应用程序中的任何位置安全地使用该对象,即使是在视图中也不必担心这些问题。这可能是提议的更好的解决方案,因为:

  • initialize()或size是一个非常人为的解决方法-如果您想初始化具有不同集合的用户,您会编写另一个方法来获取用户吗
  • 服务层事务模型是可以的,但当您想要从服务层提取对象以在控制器或视图中使用它时,同样的问题也会出现

  • 您可以执行以下操作:

    public User getByUserId(Long id, String ... fetch) {
        Criteria criteria = createCriteria();
    
        if (fetch != null) {
            for (String fieldName : fetch) {
                 criteria.setFetchMode(fieldName, FetchMode.JOIN); // fetch these fields eagerly
            }
        }
        return criteria.add(Restrictions.eq("id", id)).list();
    }
    

    @康拉德·加鲁斯请看我的问题后记,这里的文字可读性较差,所以我在这里问你。这是处理SpringDAO问题的一个好方法。