Spring Data JPA提供的关联关系(即@OneToOne, @OneToMany)以及级联操作提升了开发者的编程效率,但如果没有理解其中owning side和foreign key的关系,则会非常容易踩到坑,下面就来浅析一下Spring Data JPA中owning side及foreign key的关系。
CREATETABLE IF NOTEXISTS public.bucket ( bucket_id text COLLATE pg_catalog."default" NOTNULL, bucket_number text COLLATE pg_catalog."default" NOTNULL, bucket_description text COLLATE pg_catalog."default", status text COLLATE pg_catalog."default" NOTNULL, updated_timestamp timestampwithtime zone NOTNULL, CONSTRAINT bucket_pkey PRIMARY KEY (bucket_id) )
1 2 3 4 5 6 7 8 9 10 11
CREATETABLE IF NOTEXISTS public.bucket_dimension ( bucket_id text COLLATE pg_catalog."default" NOTNULL, weight text COLLATE pg_catalog."default", volume text COLLATE pg_catalog."default", CONSTRAINT bucket_dimension_pkey PRIMARY KEY (bucket_id), CONSTRAINT fk_bucket_dimension FOREIGN KEY (bucket_id) REFERENCES public.bucket (bucket_id) MATCH SIMPLE ONUPDATE RESTRICT ONDELETE CASCADE )
org.hibernate.exception.ConstraintViolationException: could notexecute statement] with root cause org.postgresql.util.PSQLException: ERROR: insertorupdateontable "bucket_dimension" violates foreign key constraint "fk_bucket_dimension" Detail: Key (bucket_id)=(123456) isnot present intable "bucket". at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2675) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2365) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:355) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:490) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:408)
1.4 踩坑分析
1.4.1 Owning side是什么?
此处报错的原因是对于Hibernate关联关系中的owning side认知不够明确。(Spring Data JPA底层依赖Hibernate)
Hibernate关联关系中的owning side指的是什么?
The owning side of the entity was determined by referencing both entities in the data model and identifying the entity containing the foreign key
回过头来,我们再来看一下BucketEntity中的关联关系设置,不难发现我们将@PrimaryKeyColumn放在了BucketEntity,即告知Hibernate BucketEntity才是关联关系中的owning side (即Hibernate会默认foreign key建在bucket表中)。