使用 Spring Boot starter,我正在尝试创建一个简单的示例项目,该项目涉及具有多个地址字段的用户。我正在尝试使用 @DiscriminatorColumn 和 @DiscriminatorValue 来区分用户可能拥有的不同类型的地址。
这是我项目中表格的缩略示例:
CREATE TABLE user ( id INT AUTO_INCREMENT);
CREATE TABLE user_address ( user_id INT, address_id INT);
CREATE TABLE address ( id INT AUTO_INCREMENT, TYPE VARCHAR(31));
这是我想加入的类(class):
@Entity
@DiscriminatorColumn(name = "type")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String type;
}
@Entity
@DiscriminatorValue("HOME")
public class HomeAddress extends Address {}
@Entity
@DiscriminatorValue("CURRENT")
public class CurrentAddress extends Address{}
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String type;
@OneToOne
@JoinTable(
name = "user_address",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "address_id", referencedColumnName = "id")}
)
private HomeAddress homeAddress;
@OneToOne
@JoinTable(
name = "user_address",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "address_id", referencedColumnName = "id")}
)
private CurrentAddress currentAddress;
}
我已经尝试用 @OneToMany
替换 @OneToOne
但它仍然不起作用。
我希望能够这样做的原因是我正在考虑将地址与其他实体相关联。例如,订单的 ShippingAddress 或建筑物的 LocationAddress 等。
这里是错误的转储:
Caused by: org.hibernate.boot.spi.InFlightMetadataCollector$DuplicateSecondaryTableException: Table with that name [user_address] already associated with entity
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$EntityTableXrefImpl.addSecondaryTable(InFlightMetadataCollectorImpl.java:1420) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.annotations.EntityBinder.addJoin(EntityBinder.java:972) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.annotations.EntityBinder.addJoin(EntityBinder.java:868) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.ClassPropertyHolder.addJoin(ClassPropertyHolder.java:207) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1792) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:904) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:731) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265) ~[hibernate-core-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847) ~[hibernate-entitymanager-5.0.9.Final.jar:5.0.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874) ~[hibernate-entitymanager-5.0.9.Final.jar:5.0.9.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362) ~[spring-orm-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE]
... 16 common frames omitted
最佳答案
不幸的是,您不能为这两种地址类型建立单独的关系,因为纯 JPA 无法“区分”查询中连接的结果,即不使用鉴别器值进行连接以仅获取特定类型的对象对于一个协会和另一个协会的另一种类型。相反,Hibernate 有执行此操作的方法,但超出了 JPA 规范。
所以它唯一的工作方式是让你有一个 @OneToMany
与 Address 对象的关系,作为返回给你一个多态集合包含
依次为 HomeAddress
和 CurrentAddress
对象
我有一个类似的问题。对我来说,唯一的解决办法是稍微改变一下工作方式(基本上以一种我不太喜欢的方式,但仅此而已)。
基本上你有 4 个选项(和几个备选方案):
1- 只有一个 (@OneToMany
) 关系,在检索和将它们分配到正确的字段。
2- 改变继承的设计方式。在这种情况下,您可以将地址用作 @MappedSuperclass
并将您的子类用作扩展地址类的实体。这两个类应该映射到两个单独的表中。您不需要连接表。
这就是我进行的方式,即使我不太喜欢它。
3- 抛弃继承并使用 2 个单独的表
4- 使用 hibernate (非 jpa)注释。
很抱歉没有粘贴代码,但我现在不能这样做
关于java - 使用相同的连接表引用关联实体的子类时,具有该名称 [user_address] 的表已与实体关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39052265/