ManyToOne映射在嵌入式类内部无法正常工作。

huangapple go评论100阅读模式
英文:

ManyToOne mapping not working when inside an Embeddable class

问题

我正在使用Spring Boot(2.2.6.RELEASE)和JPA开发一个项目,但我遇到一个问题让我夜不能寐...

我有一个弱实体,其主键是来自父表的复合主键组成的。

  1. +-----------------+
  2. | BAR |
  3. +-----------------+
  4. | BAR_ID PK |
  5. | NAME |
  6. +-----------------+
  7. |
  8. | +-----------------+
  9. | | FOO |
  10. +------<+-----------------+
  11. +------<| BAR_ID PK FK |
  12. | | BAZ_ID PK FK |
  13. | +-----------------+
  14. |
  15. +-----------------+
  16. | BAZ |
  17. +-----------------+
  18. | BAZ_ID PK |
  19. | NAME |
  20. +-----------------+

所以我有以下的映射...

  1. @Entity
  2. @Table(name = "FOO")
  3. public class Foo implements Serializable {
  4. @Data
  5. @Embeddable
  6. public static class ID implements Serializable {
  7. @ManyToOne
  8. @JoinColumn(name="BAR_ID")
  9. private Bar bar;
  10. @ManyToOne
  11. @JoinColumn(name="BAZ_ID")
  12. private Baz baz;
  13. }
  14. @EmbeddedId
  15. private ID id;
  16. }
  17. @Entity
  18. @Table(name = "BAR")
  19. @SequenceGenerator(name = "SEQ_BAR", sequenceName = "SEQ_BAR")
  20. public class Bar implements Serializable {
  21. @Id
  22. @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_BAR")
  23. @Column(name = "BAR_ID")
  24. private Long id;
  25. @Column(name = "NAME")
  26. private String name;
  27. }
  28. @Entity
  29. @Table(name = "BAZ")
  30. @SequenceGenerator(name = "SEQ_BAZ", sequenceName = "SEQ_BAZ")
  31. public class Baz implements Serializable {
  32. @Id
  33. @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_BAZ")
  34. @Column(name = "BAZ_ID")
  35. private Long id;
  36. @Column(name = "NAME")
  37. private String name;
  38. }

以及以下的Repository接口:

  1. @Repository
  2. public interface FooRepository extends JpaRepository<Foo, Foo.ID> {
  3. }

然后我尝试使用findById

  1. fooRepository.findById(new Foo.ID(new Bar(1), new Baz(1)));

但出现了问题:

当我调用fooRepository.findById()时,尽管从数据库中检索到了行,但是Bar和Baz的ManyToOne映射却无法正常工作。这意味着无论我是执行 foo.getId().getBar().getName() 还是 foo.getId().getBaz().getName(),Bar和Baz对象的属性 name 都是null(当然,数据库中的属性不是null)。

所以我的问题是:

这应该能够工作,对吗?
我做错了什么?
我已经尝试将fetch类型更改为EAGER,但完全没有用。

我真的非常感谢任何回复。

英文:

I am working on a project with Spring Boot (2.2.6.RELEASE) and JPA, and I am facing an issue that is bringing me nightmares...

I have a weak entity whose PK is a composite key of primary keys from parent tables.

  1. +-----------------+
  2. | BAR |
  3. +-----------------+
  4. | BAR_ID PK |
  5. | NAME |
  6. +-----------------+
  7. |
  8. | +-----------------+
  9. | | FOO |
  10. +------&lt;+-----------------+
  11. +------&lt;| BAR_ID PK FK |
  12. | | BAZ_ID PK FK |
  13. | +-----------------+
  14. |
  15. +-----------------+
  16. | BAZ |
  17. +-----------------+
  18. | BAZ_ID PK |
  19. | NAME |
  20. +-----------------+

So I have the following mapping...

  1. @Entity
  2. @Table(name = &quot;FOO&quot;)
  3. public class Foo implements Serializable {
  4. @Data
  5. @Embeddable
  6. public static class ID implements Serializable {
  7. @ManyToOne
  8. @JoinColumn(name=&quot;BAR_ID&quot;)
  9. private Bar bar;
  10. @ManyToOne
  11. @JoinColumn(name=&quot;BAZ_ID&quot;)
  12. private Baz baz;
  13. }
  14. @EmbeddedId
  15. private ID id;
  16. }
  17. @Entity
  18. @Table(name = &quot;BAR&quot;)
  19. @SequenceGenerator(name = &quot;SEQ_BAR&quot;, sequenceName = &quot;SEQ_BAR&quot;)
  20. public class Bar implements Serializable {
  21. @Id
  22. @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = &quot;SEQ_BAR&quot;)
  23. @Column(name = &quot;BAR_ID&quot;)
  24. private Long id;
  25. @Column(name = &quot;NAME&quot;)
  26. private String name;
  27. }
  28. @Entity
  29. @Table(name = &quot;BAZ&quot;)
  30. @SequenceGenerator(name = &quot;SEQ_BAZ&quot;, sequenceName = &quot;SEQ_BAZ&quot;)
  31. public class Baz implements Serializable {
  32. @Id
  33. @GeneratedValue(strategy=GenerationType.SEQUENCE, generator = &quot;SEQ_BAZ&quot;)
  34. @Column(name = &quot;BAZ_ID&quot;)
  35. private Long id;
  36. @Column(name = &quot;NAME&quot;)
  37. private String name;
  38. }

and the following Repository interface:

  1. @Repository
  2. public interface FooRepository extends JpaRepository&lt;Foo, Foo.ID&gt; {
  3. }

then I try doing findById

  1. fooRepository.findById(new Foo.ID(new Bar(1), new Baz(1));

and got the problem:

When I call fooRepository.findById(), although the row is fetched from database, ManyToOne mappings for Bar e Baz are not working properly. That means, whether I do foo.getId().getBar().getName() or foo.getId().getBaz().getName(), attribute name is null for both Bar and Baz objects (of course, the atrributes are not null in the database).

So my questions are:

This should work, right?<br/>
What am I doing wrong?<br/>
I have already tried changing fetch type to EAGER, but that didn't work at all.

I really appreciate any replies.

答案1

得分: 0

当我打印数据库执行语句时,语句为Hibernate: select foo0_.bar_id as bar_id2_2_0_,foo0_.baz_id as baz_id1_2_0_ from foo foo0_ where foo0_.bar_id=? and foo0_.baz_id=?。显然,JPA没有查询Bar和Baz表,因此foo.getBar().getName()肯定为null。

您可以使用以下方法实现相同的效果。

  1. @Entity
  2. @Table(name = "FOO")
  3. @Data
  4. public class Foo implements Serializable {
  5. @Id
  6. @GeneratedValue(strategy = GenerationType.AUTO)
  7. Long id;
  8. @ManyToOne
  9. @JoinColumn(name="BAR_ID")
  10. private Bar bar;
  11. @ManyToOne
  12. @JoinColumn(name="BAZ_ID")
  13. private Baz baz;
  14. }
  15. @Repository
  16. public interface FooRepository extends JpaRepository<Foo, Long> {
  17. Foo findByBarAndBaz(Bar bar, Baz baz);
  18. }

像这样使用它:

  1. Foo byId = fooRepository.findByBarAndBaz(new Bar(1L), new Baz(1L));
  2. Bar bar = byId.getBar();
  3. System.out.println(bar.toString());
英文:

When I print database execution statement,the statement is Hibernate: select foo0_.bar_id as bar_id2_2_0_, foo0_.baz_id as baz_id1_2_0_ from foo foo0_ where foo0_.bar_id=? and foo0_.baz_id=?.Obviously the JPA does not query the Bar and Baz tables,so foo.getBar().getName() certainly will be null.

You can use follow way to achieve the same effect.

  1. @Entity
  2. @Table(name = &quot;FOO&quot;)
  3. @Data
  4. public class Foo implements Serializable {
  5. @Id
  6. @GeneratedValue(strategy = GenerationType.AUTO)
  7. Long id;
  8. @ManyToOne
  9. @JoinColumn(name=&quot;BAR_ID&quot;)
  10. private Bar bar;
  11. @ManyToOne
  12. @JoinColumn(name=&quot;BAZ_ID&quot;)
  13. private Baz baz;
  14. }
  15. @Repository
  16. public interface FooRepository extends JpaRepository&lt;Foo, Long&gt; {
  17. Foo findByBarAndBaz(Bar bar, Baz baz);
  18. }

use it like this:

  1. Foo byId = fooRepository.findByBarAndBaz(new Bar(1L), new Baz(1L));
  2. Bar bar = byId.getBar();
  3. System.out.println(bar.toString());

huangapple
  • 本文由 发表于 2020年10月23日 05:17:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/64490678.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定