在Embeddable类内部时,ManyToOne映射不起作用



我正在使用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());

最新更新