代码之家  ›  专栏  ›  技术社区  ›  Maiko Kingma

hibernate何时加载映射关系

  •  0
  • Maiko Kingma  · 技术社区  · 6 年前

    我正在创建一个spring boot应用程序并使用它的内置 JpaRepository 用于存储实体的接口。我有以下两个实体(为了可读性删除了getter和setter):

    配置文件实体

    @Entity
    public class Profile {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;
    
        @OneToMany(mappedBy = "profileOne", orphanRemoval = true)
        private List<Match> matchOnes;
    
        @OneToMany(mappedBy = "profileTwo", orphanRemoval = true)
        private List<Match> matchTwos;
    }
    

    匹配实体

    @Entity
    @Table(uniqueConstraints={
        @UniqueConstraint(columnNames = { "profileOne_id", "profileTwo_id" })
    }) 
    public class Match {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;
    
        @ManyToOne
        @JoinColumn(name = "profileOne_id")
        private Profile profileOne;
    
        @ManyToOne
        @JoinColumn(name = "profileTwo_id")
        private Profile profileTwo;
    }
    

    了解 JPA储蓄 行为我编写了以下单元测试。

    @RunWith(SpringRunner.class)
    @DataJpaTest
    public class IProfileDaoTest {
    
        @Autowired
        private IProfileDao profileDao; //This class extends JpaRepository<Profile, long>
    
        @Autowired
        private IMatchDao matchDao; //This class extends JpaRepository<Match, long>
    
        @Test
        public void saveProfileTest() throws Exception {
    
        @Test
        public void profileMatchRelationTest() throws Exception {
            //Test if matches stored by the IMatchDao are retrievable from the IProfileDao
            Profile profileOne = new Profile("Bob"),
                profileTwo = new Profile("Alex");
            profileDao.saveAndFlush(profileOne);
            profileDao.saveAndFlush(profileTwo);
            matchDao.saveAndFlush(new Match(profileOne, profileTwo));
            profileOne = profileDao.getOne(profileOne.getId());
            Assert.assertEquals("Match not retrievable by profile.", 1, profileOne.getMatchOnes().size());
        }
    }
    

    现在,我希望匹配项已经出现在概要文件实体中,但它们没有出现。我还尝试添加 CascadeType.ALL @ManyToOne 匹配实体中的注释并添加 FetchType.EAGER @OneToMany 轮廓图元中的注释。

    是否可以通过在profileDao中请求概要文件来获得与matchDao一起保存的匹配?或者我应该用一个单独函数的概要文件来查找匹配项吗?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Maiko Kingma    6 年前

    由于性能原因(可能还有其他原因),Spring数据存储库不会立即写入数据库。在测试中,如果需要测试查询方法,则需要使用 @DataJpaTest (存储库在后台使用的只是实体管理器,但有一些方便的测试方法)。

    更新1: 匹配项不会添加到配置文件中。为了确保关系是双向的,匹配项应该有配置文件,但配置文件也应该有匹配项。

    尝试以下操作:

    @RunWith(SpringRunner.class)
    @DataJpaTest
    public class IProfileDaoTest {
    
        @Autowired
        private IProfileDao profileDao; //This class extends JpaRepository<Profile, long>
    
        @Autowired
        private IMatchDao matchDao; //This class extends JpaRepository<Match, long>
    
        @Autowired
        private TestEntityManager testEntityManager;
    
        @Test
        public void saveProfileTest() throws Exception {
    
        @Test
        public void profileMatchRelationTest() throws Exception {
            //Test if matches stored by the IMatchDao are retrievable from the IProfileDao
            Profile profileOne = new Profile("Bob"),
                profileTwo = new Profile("Alex");
    
            //Persist the profiles so they exist when they are added to the match
            entityManager.persistAndFlush(profileOne);
            entityManager.persistAndFlush(profileTwo);
    
            //Create and persist the match with two profiles
            Match yourMatch = entityManager.persistFlushFind(new Match(profileOne, profileTwo));
    
            //Add the match to both profiles and persist them again.
            profileOne.matchOnes.add(yourMatch);
            entityManager.persistAndFlush(profileOne);
            profileTwo.matchTwos.add(yourMatch);
            entityManager.persistAndFlush(profileTwo);
    
            profileOne = profileDao.getOne(profileOne.getId());
            Assert.assertEquals("Match not retrievable by profile.", 1, profileOne.getMatchOnes().size());
        }
    }
    
        2
  •  0
  •   Jens Schauder    6 年前

    测试中的所有内容都发生在同一个JPA会话中。这样的会话保证每个实体只包含一次。所以当你执行

    profileOne = profileDao.getOne(profileOne.getId());
    

    您将获得您在上面创建的5行的确切实例。 Hibernate或任何其他JPA实现都不会更改实体中的任何内容以进行加载。

    如果要实际重新加载实体,则必须首先从实体管理器中将其逐出,或者使用新的 Session / EntityManager

    有关更多详细信息,请参阅JPA规范的第3章。