在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
    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());