Spring-Data 中的父对象不获取子对象

Posted

技术标签:

【中文标题】Spring-Data 中的父对象不获取子对象【英文标题】:Child objects aren't fetched with parent object in Spring-Data 【发布时间】:2020-01-26 21:32:53 【问题描述】:

我对 Hibernate 很陌生,我已经在父对象和子对象之间设置了 @OneToMany 双向关系,并期望当我将所有内容保存在数据库中时,将父对象设置为子对象(因为子对象是关系),当我使用 ORM 获取父对象时,我希望也获取一个子对象,但作为回报,我看到零个子对象。

据我在互联网上阅读的内容所了解的,当我将子对象作为与父级的关系的所有者时,完整的 ORM 应该会根据预定义的关系映射来连接两个对象.这些信息正确吗?

@Entity
@Table(name = "stream")
@SequenceGenerator(name = "sequence", sequenceName = "stream_id", allocationSize = 1)
public class StreamEntity extends EntityWithId 

    // @MappedSuperclass with ID 

    @Column(name = "request_id")
    @OneToMany(
            mappedBy = "streamEntity",
            fetch = FetchType.LAZY
    )
    private List<RequestEntity> requestEntities = new ArrayList<>();

    // getters setters


@Entity
@Table(name = "request")
@SequenceGenerator(name = "sequence", sequenceName = "request_id", allocationSize = 1, initialValue = 1)
public class RequestEntity extends EntityWithId 

    // @MappedSuperclass with ID 

    @JoinColumn(name = "stream_id")
    @ManyToOne(fetch = FetchType.LAZY)
    private StreamEntity streamEntity;

    // getters setters

一些测试:

@Test
public void createStreamWithSeveralStreamTargetsAndDeleteStream() 
    List<StreamEntity> streamEntities = createStream(1); // stream object is persisted here

    List<RequestEntity> requestEntitySave = createRequest(1, streamEntityCheck);
    assertEquals(1, requestEntitySave.size()); // request entity is persisted with the stream object into the database

    List<StreamEntity> streamEntities = streamDao.findAll();
    assertEquals(1, streamEntities.size());
    StreamEntity streamEntity2 = streamEntities.get(0);
    streamEntity2.getRequestEntities(); - this collection shows 0

我错过了什么?

更新: 正如@Alan Hay 建议的那样,我已经在我的测试中添加了一个@Persistent 上下文,现在它看起来像这样:

@PersistenceContext
    private EntityManager em;


@Test
    public void createStreamWithSeveralStreamTargetsAndDeleteStream() 
        List<StreamEntity> streamEntities = createStream(1); // stream object is persisted here

        List<RequestEntity> requestEntitySave = createRequest(1, streamEntityCheck);
        assertEquals(1, requestEntitySave.size()); // request entity is persisted with the stream object into the database

        em.clear();

List<RequestEntity> requestEntities = requestDao.findAll();
        assertEquals(1, requestEntities.size()); // retirns zero objects

        List<StreamEntity> streamEntities = streamDao.findAll();
        assertEquals(1, streamEntities.size());
        StreamEntity streamEntity2 = streamEntities.get(0);
        streamEntity2.getRequestEntities();// this collection shows 0
    

完成此操作后,我在 requestDao.findAll(); 上得到零个对象;步。我已在上一步中提交了这些更改,为什么我无法获取此实体?

【问题讨论】:

看这里:Difference between FetchType LAZY and EAGER in Java Persistence API? 感谢您的回答,我已经了解了 fetch 类型之间的区别,据我了解 FetchType.LAZY 它应该至少返回代理对象,但它什么也不返回。跨度> 【参考方案1】:

由于一级缓存的概念,您创建和保存的初始对象与您加载的对象是同一个实例。由于您没有将创建的请求实体添加到内存模型中,而只是将其持久化到数据库中,因此内存模型中不存在关系。

要获得所需的结果,您需要清除保存和重新加载之间的持久性上下文。

@Test
    public void createStreamWithSeveralStreamTargetsAndDeleteStream() 
        List<StreamEntity> streamEntities = createStream(1); 

        List<RequestEntity> requestEntitySave = createRequest(1, streamEntityCheck);
        assertEquals(1, requestEntitySave.size()); 

        //you need to clear the persistence context here
        //now a db query should execute.
        //Inject the entitymanager to your test @PersistenceContext EntityManager em;
        em.clear();

        List<StreamEntity> streamEntities = streamDao.findAll();
        assertEquals(1, streamEntities.size());
        StreamEntity streamEntity2 = streamEntities.get(0);
        streamEntity2.getRequestEntities(); - this collection shows 0

   

【讨论】:

谢谢你的回答,我还有几个问题。我正在使用带有这种花哨的模糊 CRUD 方法的 spring-data,我认为他们正在做所有这些事情,即开箱即用地清除上下文等,对吗?我是否需要对 spring 数据执行任何其他配置才能使其按预期工作? 一级缓存由hibernate管理,无法绕过。通常你会想要它。确保内存模型的一致性是您的责任。

以上是关于Spring-Data 中的父对象不获取子对象的主要内容,如果未能解决你的问题,请参考以下文章

Django:获取子对象匹配条件的父对象

SimpleRepository 中的父对象和子对象

DOM操作基础

如何从可能是与给定 id 匹配的父级或子级之一的列表中获取对象

在 Django 的父管理视图中将子对象链接到父对象

Django 无法保存子对象的父 ID