OneToMany with Embeddable无法正常工作

时间:2016-01-14 13:55:50

标签: java spring hibernate jpa

我正在使用Spring Boot 1.3.1和Hibernate 4.3.11和JPA。我有以下映射:

@Entity
public class Game {
   @EmbeddedId
   private GameId id;

   @Embedded
   private Prize prize;
}

@Embeddable
public class Prize {
   private String name;
   @OneToMany
   @Cascade(CascadeType.ALL)
   private List<ImageReference> images;
}

@Entity
public class ImageReference {
  @EmbeddedId
  private ImageReferenceId id;
  private ImageType type;
  private ImageFormat format;
}

@Embeddable
public class GameId {
  private UUID id;
}

@Emdeddable
public class ImageReferenceId {
  private UUID id;
}

我正在使用Spring Data JPA创建一个存储库(从CrudRepository扩展)

使用此映射时,会创建3个表:gamegame_imagesimage_reference。但是,game_images表格没有填满。 game中有1个插入,image_reference中有3个插入(我的测试为'images'集合添加了3个项目)。知道为什么会这样吗?

我的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration({Application.class, GameRepositoryTest.TestConfiguration.class})
@TestPropertySource(locations = "classpath:application-test.properties")
public class GameRepositoryTest {

    @Autowired
    private GameRepository repository;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void test()
    {
        Game game = repository.save(Games.newRandomGameWithPrizeImages());
        assertThat( game ).isNotNull();

        assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM game", Long.class )).isEqualTo(1);
        assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM image_reference", Long.class )).isEqualTo(3);
        assertThat(jdbcTemplate.queryForObject("SELECT COUNT(*) FROM game_images", Long.class )).isEqualTo(3);
    }

    @Configuration
    static class TestConfiguration
    {
        @Bean
        public ImageRepository imageRepository() {
            return new LocalFileSystemImageRepository(new InMemoryUniqueIdGenerator());
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我在JPA规范中找不到详细定义如何将可嵌入类中的关系映射到DB。在直接实体OneToMany关系的情况下,如何可以映射而不是连接表是默认解决方案,即。很多方面的外键。您可以通过在@JoinColumn

中指定Prize来实现这一目标
@OneToMany
@Cascade(CascadeType.ALL)
@JoinColumn(name="GAME_ID")
private List<ImageReference> images;

或者,如果您不想在Prize中隐藏它,请使用@AssociationOverride中的Game

@Embedded
@AssociationOverride(name= "images", joinColumns = @JoinColumn(name="GAME_ID"))
private Prize prize;

然后,game_images表将过时。

编辑: Hibernate有一个错误HHH-4384,如果你想使用@JoinColumn,你需要在嵌入类的关系中添加@AssociationOverride注释(即使没有任何注释值)。