You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA实体findAll()返回时关联对象列表为空的测试问题排查

Hey there, let's break down why your test is failing and fix it step by step!

1. The Core Issue: Unmaintained Bidirectional Association

Your MyEntity and MyObject have a bidirectional @OneToMany/@ManyToOne relationship, but you're only setting one side of it. Since MyObject owns the relationship (it holds the foreign key my_entity_id in the database), you must set the myEntityId field on each MyObject when creating the association. Right now, those fields are null, so when you save MyEntity, Hibernate doesn't populate the foreign key in the myobject table—meaning there's no link between the two entities in the database, so your JOIN FETCH query can't find any related MyObjects.

Fix this by updating your createMyEntity method to set the parent MyEntity on each MyObject:

private MyEntity createMyEntity(List<MyObject> myObjects, int someId) {
    MyEntity myEntity = new MyEntity(someId, myObjects);
    // Maintain the bidirectional relationship
    for (MyObject obj : myObjects) {
        obj.setMyEntityId(myEntity);
    }
    return myEntity;
}

2. Conflict Between Custom SessionFactory and Spring's Test Context

Your SessionFactoryRule is creating a completely separate Hibernate SessionFactory and Session from the one used by Spring's JpaRepository. When you call myEntityRepository.save(myEntity), it uses Spring's managed Session, but your sf.commit() is committing a different transaction from your custom Session. This leads to inconsistent state between the two contexts—your save operation might not even be persisted to the same in-memory H2 database instance that your repository is querying.

Remove the SessionFactoryRule entirely—Spring Boot Test handles all of this for you out of the box. Add @Transactional to your test method (or class) to let Spring manage the transaction, and it will automatically roll back after the test to keep your database clean.

Updated test class:

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyApplicationTests {

    @Autowired
    MyEntityRepository myEntityRepository;

    @Test
    @Transactional // Let Spring manage the transaction
    public void returnsMyEntityForSomeId() {
        int someId = 0;
        List<MyObject> myObjects = createMyObjects();
        int numberOfMyObjectsIn = myObjects.size();
        MyEntity myEntity = createMyEntity(myObjects, someId);
        
        // Save using Spring's repository (no need for manual commit)
        MyEntity saved = myEntityRepository.save(myEntity);

        // Test retrieval with eager fetch
        MyEntity thisEntity = myEntityRepository.findByIdAndFetchMyObjectsEagerly(someId);
        assertNotNull(thisEntity);
        assertNotNull(thisEntity.getMyObjects());
        
        // This should now pass!
        assertEquals(numberOfMyObjectsIn, thisEntity.getMyObjects().size());
    }

    // ... rest of your methods (createMyObjects, updated createMyEntity)
}

3. Verify Your Repository Query (Optional)

Your JOIN FETCH query looks correct, but just to make sure, you can also use Spring Data JPA's built-in query derivation or ensure the entity aliases are clear. Alternatively, if you want to use findById, you can use EntityManager to fetch the association eagerly in the test, but your custom query should work once the foreign keys are populated.

Bonus: Simplify H2 Configuration

Spring Boot auto-configures an in-memory H2 database for tests by default, so you don't need to manually set up the SessionFactory with H2 properties. Just make sure you have the H2 dependency in your pom.xml or build.gradle, and Spring will handle the rest.

After making these changes, your test should correctly persist the association between MyEntity and MyObject, and the JOIN FETCH query will retrieve the related objects as expected.

内容的提问来源于stack exchange,提问作者bekimarton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:59:03