问题描述
我正在使用Spring Boot(2.2.6.RELEASE)和JPA进行一个项目,而我正面临着一个令我噩梦般的问题...
+-----------------+
| 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
public interface FooRepository extends JpaRepository<Foo,Foo.ID> {
}
然后我尝试执行findById
fooRepository.findById(new Foo.ID(new Bar(1),new Baz(1));
出现问题:
当我调用fooRepository.findById()时,尽管从数据库中获取了该行,但是Bar e Baz的ManyToOne映射无法正常工作。这意味着,无论我做foo.getId().getBar().getName()
还是foo.getId().getBaz().getName()
,Bar和Baz对象的属性name
都为空(当然,数据库中的属性也不为空)。
所以我的问题是:
这应该可行,对吧?
我在做什么错了?
我已经尝试将提取类型更改为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());