我正在使用Spring Boot(2.2.6.RELEASE(和JPA进行一个项目,我面临着一个让我做噩梦的问题。。。
我有一个弱实体,它的PK是父表主键的组合键。
+-----------------+
| BAR |
+-----------------+
| BAR_ID PK |
| NAME |
+-----------------+
|
| +-----------------+
| | FOO |
+------<+-----------------+
+------<| BAR_ID PK FK |
| | BAZ_ID PK FK |
| +-----------------+
|
+-----------------+
| BAZ |
+-----------------+
| BAZ_ID PK |
| NAME |
+-----------------+
所以我有下面的映射。。。
@Entity
@Table(name = "FOO")
public class Foo implements Serializable {
@Data
@Embeddable
public static class ID implements Serializable {
@ManyToOne
@JoinColumn(name="BAR_ID")
private Bar bar;
@ManyToOne
@JoinColumn(name="BAZ_ID")
private Baz baz;
}
@EmbeddedId
private ID id;
}
@Entity
@Table(name = "BAR")
@SequenceGenerator(name = "SEQ_BAR", sequenceName = "SEQ_BAR")
public class Bar implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_BAR")
@Column(name = "BAR_ID")
private Long id;
@Column(name = "NAME")
private String name;
}
@Entity
@Table(name = "BAZ")
@SequenceGenerator(name = "SEQ_BAZ", sequenceName = "SEQ_BAZ")
public class Baz implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "SEQ_BAZ")
@Column(name = "BAZ_ID")
private Long id;
@Column(name = "NAME")
private String name;
}
以及以下Repository接口:
@Repository
public interface FooRepository extends JpaRepository<Foo, Foo.ID> {
}
然后我试着做findById
fooRepository.findById(new Foo.ID(new Bar(1), new Baz(1));
并得到了问题:
当我调用fooRepository.findById((时,尽管该行是从数据库中提取的,但Bare Baz的ManyToOne映射无法正常工作。这意味着,无论我执行foo.getId().getBar().getName()
还是foo.getId().getBaz().getName()
,Bar和Baz对象的属性name
都为null(当然,atrributes在数据库中不为null(。
所以我的问题是:
这应该行得通,对吧
我做错了什么
我已经尝试过将fetch类型更改为EAGER,但根本不起作用。
我真的很感谢你的回复。
当我打印数据库执行语句时,该语句是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()
肯定会为空。
你可以用下面的方法来达到同样的效果。
@Entity
@Table(name = "FOO")
@Data
public class Foo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
@ManyToOne
@JoinColumn(name="BAR_ID")
private Bar bar;
@ManyToOne
@JoinColumn(name="BAZ_ID")
private Baz baz;
}
@Repository
public interface FooRepository extends JpaRepository<Foo, Long> {
Foo findByBarAndBaz(Bar bar, Baz baz);
}
这样使用:
Foo byId = fooRepository.findByBarAndBaz(new Bar(1L), new Baz(1L));
Bar bar = byId.getBar();
System.out.println(bar.toString());