gpt4 book ai didi

java - 如何使用@EmbeddedId 在两个表之间进行映射?

转载 作者:行者123 更新时间:2023-12-03 23:42:22 24 4
gpt4 key购买 nike

所以我这里有一个看起来像这样的图表,
可以在此 Answer Here 中找到.

 +---------------+     +-------------------+
| PRODUCTS |-----< PRODUCT_VARIANTS |
+---------------+ +-------------------+
| #product_id | | #product_id |
| product_name | | #variant_id |
+---------------+ | sku_id |
| +-------------------+
| |
+--------^--------+ +--------^--------+
| PRODUCT_OPTIONS |-----< VARIANT_VALUES |
+-----------------+ +-----------------+
| #product_id | | #product_id |
| #option_id | | #variant_id |
+--------v--------+ | #option_id |
| | value_id |
+-----------------+ +--------v--------+
| OPTIONS | |
+-----------------+ |
| #option_id | |
| option_name | |
+-----------------+ |
| |
+-------^-------+ |
| OPTION_VALUES |---------------+
+---------------+
| #option_id |
| #value_id |
| value_name |
+---------------+
我设法在我的 Spring 应用程序中实现了整个图表,除了表 VARIANT_VALUES问题在于设计建议表 PRODUCT_OPTIONS , OPTION_VALUESPRODUCT_VARIANTS有复合 Id(主键),我使用 @EmbeddedId 实现
其中三个。
如下
前任。 //PRODUCT_VARIANTS
@Data
@NoArgsConstructor
@Entity
@Table(name = "product_variants")
public class ProductVariant {

@EmbeddedId
private ProductVariantId productVariantId;

@NotNull
private Double price;

@MapsId("productId")
@ManyToOne(fetch = FetchType.LAZY)
private Product product;

//other properties
}
//ProductVariantId
@Data
@Embeddable
public class ProductVariantId implements Serializable {

@EqualsAndHashCode.Include
private Long productVariantId;
@EqualsAndHashCode.Include
private Long productId;
}
现在我需要用 PRODUCT_OPTIONS 再次映射这三个表( OPTION_VALUESPRODUCT_VARIANTSVARIANT_VALUES )
所以我尝试了这种方法 //VariantValue
@Data
@NoArgsConstructor
@Entity
@Table(name = "variant_values")
public class VariantValue {

@EmbeddedId
private VariantValueId variantValueId;

@MapsId("productVariantId")
@ManyToOne(fetch = FetchType.LAZY)
private ProductVariant productVariant;

@MapsId("productOptionId")
@ManyToOne(fetch = FetchType.LAZY)
private ProductOption productOption;

@MapsId("optionValueId")
@ManyToOne(fetch = FetchType.LAZY)
private OptionValue optionValue;

}
//VariantValueId
@Embeddable
@Data
public class VariantValueId implements Serializable {


@EqualsAndHashCode.Include
@Embedded
private ProductVariantId productVariantId;

@EqualsAndHashCode.Include
@Embedded
private ProductOptionId productOptionId;

@EqualsAndHashCode.Include
@Embedded
private OptionValueId optionValueId;
}
但它最终创建了一个表,其中包含所有三个表中的每个 Id,
当我添加一个 @EmbddedVariantValueId它生成两列,我找不到任何方法来排除一个值并使用另一个值,
所以生成的表现在看起来像这样 //variant_values
product_option_option_option_id [PK]
product_option_ptoduct_product_id [PK]
product_variant_ptoduct_product_id [PK]
product_variant_ptoduct_variant_id [PK]
product_value_option_option_id [PK]
product_value_option_value_id [PK]
那么我怎样才能实现这个只有 product_id [PK] , variant_id [PK] , option_id [PK]value_id正如设计所暗示的那样?
编辑 1
我尝试了克里斯蒂安贝科夫的方法
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "product_variants")
public class ProductVariant extends UserDateAudit {

@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "productVariantId", column = @Column(name = "variant_id")),
@AttributeOverride(name = "productId", column = @Column(name = "product_id"))
})
private ProductVariantId productVariantId;


@NotNull
private Double price;

//many to many with product entity, option entity and optionValue entity
@MapsId("productId")
@ManyToOne(fetch = FetchType.LAZY)
private Product product;

@OneToMany(mappedBy = "productVariant", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<VariantValue> variantValues;

}

@Data
@Embeddable
public class ProductVariantId implements Serializable {

private Long productVariantId;
private Long productId;
}

@Data
@NoArgsConstructor
@Entity
@Table(name = "variant_values")
public class VariantValue {
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "productVariantId", column = @Column(name = "variant_id")),
@AttributeOverride(name = "productId", column = @Column(name = "product_id"))
@AttributeOverride(name = "optionId", column = @Column(name = "option_id")),
@AttributeOverride(name = "valueId", column = @Column(name = "value_id"))
})
private VariantValueId variantValueId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "variant_id", referencedColumnName = "variant_id", insertable = false, updatable = false),
@JoinColumn(name = "product_id", referencedColumnName = "product_id", insertable = false, updatable = false)
})
private ProductVariant productVariant;

//other mappings
我收到以下错误
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: product_id in product_variants
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:113) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:691) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:197) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1206) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925) ~[spring-context-5.3.1.jar:5.3.1]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.1.jar:5.3.1]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) ~[spring-boot-2.4.0.jar:2.4.0]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) ~[spring-boot-2.4.0.jar:2.4.0]
at com.ecommerce.ECommerceApplication.main(ECommerceApplication.java:10) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.0.jar:2.4.0]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name: product_id in product_variants
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.1.jar:5.3.1]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330) ~[spring-beans-5.3.1.jar:5.3.1]
... 27 common frames omitted
Caused by: org.hibernate.MappingException: Unable to find column with logical name: product_id in product_variants
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:854) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:255) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:101) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processEndOfQueue(InFlightMetadataCollectorImpl.java:1823) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processFkSecondPassesInOrder(InFlightMetadataCollectorImpl.java:1767) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1655) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:286) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.23.Final.jar:5.4.23.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.1.jar:5.3.1]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.1.jar:5.3.1]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]

最佳答案

试试这样的:

@Data
@NoArgsConstructor
@Entity
@Table(name = "product_variants")
public class ProductVariant {

@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "productVariantId", column = @Column(name = "variant_id")),
@AttributeOverride(name = "productId", column = @Column(name = "product_id"))
})
private ProductVariantId productVariantId;

@NotNull
private Double price;

@MapsId("productId")
@ManyToOne(fetch = FetchType.LAZY)
private Product product;

//other properties
}

@Data
@Embeddable
public class ProductVariantId implements Serializable {

@EqualsAndHashCode.Include
private Long productVariantId;
@EqualsAndHashCode.Include
private Long productId;
}

@Data
@NoArgsConstructor
@Entity
@Table(name = "variant_values")
public class VariantValue {

@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "productVariantId", column = @Column(name = "variant_id")),
@AttributeOverride(name = "productId", column = @Column(name = "product_id")),
@AttributeOverride(name = "optionId", column = @Column(name = "option_id")),
@AttributeOverride(name = "valueId", column = @Column(name = "value_id"))
})
private VariantValueId variantValueId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "variant_id", referencedColumnName = "variant_id", insertable = false, updatable = false),
@JoinColumn(name = "product_id", referencedColumnName = "product_id", insertable = false, updatable = false)
})
private ProductVariant productVariant;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "option_id", referencedColumnName = "option_id", insertable = false, updatable = false),
@JoinColumn(name = "product_id", referencedColumnName = "product_id", insertable = false, updatable = false)
})
private ProductOption productOption;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "option_id", referencedColumnName = "option_id", insertable = false, updatable = false),
@JoinColumn(name = "value_id", referencedColumnName = "value_id", insertable = false, updatable = false)
})
private OptionValue optionValue;

}

@Embeddable
@Data
public class VariantValueId implements Serializable {


@EqualsAndHashCode.Include
private Long productVariantId;
@EqualsAndHashCode.Include
private Long productId;
@EqualsAndHashCode.Include
private Long optionId;
@EqualsAndHashCode.Include
private Long valueId;
}
编辑:
然后试试这个:
@Data
@NoArgsConstructor
@Entity
@Table(name = "product_variants")
public class ProductVariant {

@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "productVariantId", column = @Column(name = "variant_id")),
@AttributeOverride(name = "productId", column = @Column(name = "product_id"))
})
private ProductVariantId productVariantId;

@NotNull
private Double price;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColum(name = "product_id", insertable = false, updatable = false)
private Product product;

//other properties
}

关于java - 如何使用@EmbeddedId 在两个表之间进行映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64993785/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com