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

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

ManyToOne mapping not working when inside an Embeddable class

问题

我正在使用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接口:

	@Repository
	public interface FooRepository extends JpaRepository<Foo, Foo.ID> {

	}

然后我尝试使用findById

	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.

	+-----------------+
	|       BAR       |
	+-----------------+
	| BAR_ID PK       |
	| NAME            |
	+-----------------+
			|
			|		+-----------------+
			|		|       FOO       |
			+------&lt;+-----------------+
			+------&lt;| BAR_ID PK FK    |
			|		| BAZ_ID PK FK    |
			|		+-----------------+
			|
	+-----------------+
	|       BAZ       |
	+-----------------+
	| BAZ_ID PK       |
	| NAME            |
	+-----------------+

So I have the following mapping...

	@Entity
	@Table(name = &quot;FOO&quot;)
	public class Foo implements Serializable {

		@Data
		@Embeddable
		public static class ID implements Serializable {
			@ManyToOne
			@JoinColumn(name=&quot;BAR_ID&quot;)
			private Bar bar;

			@ManyToOne
			@JoinColumn(name=&quot;BAZ_ID&quot;)
			private Baz baz;
		}

		@EmbeddedId
		private ID id;
	}


	@Entity
	@Table(name = &quot;BAR&quot;)
	@SequenceGenerator(name = &quot;SEQ_BAR&quot;, sequenceName = &quot;SEQ_BAR&quot;)
	public class Bar implements Serializable {

		@Id
		@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = &quot;SEQ_BAR&quot;)
		@Column(name = &quot;BAR_ID&quot;)
		private Long id;

		@Column(name = &quot;NAME&quot;)
		private String name;

	}

	@Entity
	@Table(name = &quot;BAZ&quot;)
	@SequenceGenerator(name = &quot;SEQ_BAZ&quot;, sequenceName = &quot;SEQ_BAZ&quot;)
	public class Baz implements Serializable {

		@Id
		@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = &quot;SEQ_BAZ&quot;)
		@Column(name = &quot;BAZ_ID&quot;)
		private Long id;

		@Column(name = &quot;NAME&quot;)
		private String name;

	}

and the following Repository interface:

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

	}

then I try doing findById

	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。

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

@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());
英文:

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.

@Entity
@Table(name = &quot;FOO&quot;)
@Data
public class Foo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    @ManyToOne
    @JoinColumn(name=&quot;BAR_ID&quot;)
    private Bar bar;
    @ManyToOne
    @JoinColumn(name=&quot;BAZ_ID&quot;)
    private Baz baz;

}

@Repository
public interface FooRepository extends JpaRepository&lt;Foo, Long&gt; {
    Foo findByBarAndBaz(Bar bar, Baz baz);
}

use it like this:

Foo byId = fooRepository.findByBarAndBaz(new Bar(1L), new Baz(1L));
Bar bar = byId.getBar();
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:

确定