Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/159.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
如何急切地获取JPA和Hibernate中的数据,以便在会话之外使用?_Hibernate_Jpa_Spring Data Jpa - Fatal编程技术网

如何急切地获取JPA和Hibernate中的数据,以便在会话之外使用?

如何急切地获取JPA和Hibernate中的数据,以便在会话之外使用?,hibernate,jpa,spring-data-jpa,Hibernate,Jpa,Spring Data Jpa,我不熟悉Hibernate和JPA,但似乎无法让它工作 这些模型是持久化的,其中EntityHistory在EntityHistoryChange表中有一组链接的更改: @Table @RooJavaBean @RooJpaActiveRecord public class EntityHistory { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") privat

我不熟悉Hibernate和JPA,但似乎无法让它工作

这些模型是持久化的,其中
EntityHistory
EntityHistoryChange
表中有一组链接的更改:

@Table
@RooJavaBean
@RooJpaActiveRecord
public class EntityHistory {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "history")
    private Set<EntityHistoryChange> changes = new HashSet<>();
}


@Table
@AssociationOverride(name="history", joinColumns = @JoinColumn(name ="entityHistoryId"))
@RooJavaBean
@RooJpaActiveRecord
public class EntityHistoryChange {

    @Lob
    @Type(type = "org.hibernate.type.TextType")
    private String change;
} 
@表格
@爪哇豆
@RooJPA活动记录
公共类实体历史{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
@列(name=“id”)
私人长id;
@OneToMany(cascade=CascadeType.ALL,mappedBy=“history”)
私有集更改=新HashSet();
}
@桌子
@AssociationOverride(name=“history”,joinColumns=@JoinColumn(name=“entityHistoryId”))
@爪哇豆
@RooJPA活动记录
公共类EntityHistoryChange{
@高球
@类型(Type=“org.hibernate.Type.TextType”)
私有字符串更改;
} 
然后,我需要一次访问所有这些数据,以便将其序列化以进行计划的导出

我有一个带有计划作业的服务:

// Trying to fetch entire object so can use it outside of session
@Service
public class ScheduledExecutor {

    @Scheduled(cron = "0 05 0 * * ?")
    public void extractHistory() {      
        long lastId = 12345l;
        List<EntityHistory> history = findHistoriesWithIdGreater(lastId);

        for(EntityHistoryChange change : history.get(6).getChanges()){
            logger.info("                    change is: " + change.getChange());
        }
    }

    public static List<EntityHistory> findHistoriesWithIdGreater(Long lastId) {
        TypedQuery<EntityHistory> query = entityManager().createQuery(
                "select a from EntityHistory a join fetch a.changes c where a.id > :lastId order by a.id",
                EntityHistory.class);

        query.setParameter("lastId", lastId);
        return query.getResultList();
    }
}
//尝试获取整个对象,以便可以在会话之外使用它
@服务
公共类调度执行器{
@已计划(cron=“0 05 0**?”)
public void extractHistory(){
长lastId=12345l;
List history=findHistorieswithId大于(lastId);
for(EntityHistoryChange更改:history.get(6.getChanges()){
info(“更改为:+change.getChange());
}
}
公共静态列表查找具有更大ID的历史(长lastId){
TypedQuery query=entityManager().createQuery(
“从EntityHistory a join fetch a.changes a.c中选择a.id>:lastId order by a.id”,
实体历史类);
setParameter(“lastId”,lastId);
返回query.getResultList();
}
}
但当它运行时,我一直会遇到以下错误:

org.hibernate.LazyInitializationException:无法执行请求的延迟初始化[com.company.model.EntityHistory.changes]-没有会话和设置不允许在会话外部加载


我认为,通过在JPQL查询中放入
连接获取
,它应该急切地获取该连接中的所有数据

fetch应该完成这项工作,但这只是对hibernate的一个建议,如果需要的话 没有,那么这可能是复杂映射的结果

因此,尝试一种不同的方法,我能够通过以下方式构建DAO来实现我所追求的目标:

/** DAO to interact with EntityHistory records */
public interface EntityHistoryDao extends JpaRepository<EntityHistory, Long> {

    /** Returns EntityHistory records with IDs greater than the given ID */
    @QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE, value = "500"))
    Stream<EntityHistory> findByIdGreaterThanOrderByIdAsc(Long id);
}

此注释将实现以下功能:

@EntityGraph(attributePaths = { "changes" })
Stream<EntityHistory> findByIdGreaterThanOrderByIdAsc(Long id);
@EntityGraph(attributePath={“changes”})
流findByidCreaterAnorderByIdasc(长id);
它将创建一个连接查询(列出的属性将被急切地加载),因此所有数据都将在一个查询中加载,因此您甚至不需要服务方法上的
@Transactional
注释


编辑 我忽略了
返回类型。(我以前从未在存储库中将流用作返回类型)
我仍然相信,如果您将返回类型更改为
List
,那么它就会工作。

生成的SQL语句是什么样子的?@SimonMartinelli我不确定。我怎样才能打开它们看呢?根据Andronicus的反馈,听起来JPQL中的“fetch”命令被hibernate视为一个提示,不一定强制执行。无论如何,我确实找到了一个适合我的目的的解决方案,我会在一个新的答案中更新。我测试了这个,但事实并非如此。删除服务方法上的
@Transactional
注释,在DAO方法上应用
@EntityGraph
注释会产生类似的问题:
InvalidDataAccessApiUsageException:您试图执行流式查询方法,而不使用保持连接打开的周围事务,以便流可以实际使用。确保使用流的代码使用@Transactional或任何其他方式声明(只读)事务。
使用
列表而不是
流来尝试它
再次导致原始错误:
LazyInitializationException:无法执行请求的延迟初始化[com.company.model.EntityHistory.changes]-无会话和设置不允许在会话之外加载
@EntityGraph(attributePaths = { "changes" })
Stream<EntityHistory> findByIdGreaterThanOrderByIdAsc(Long id);