Java 当使用同一联接表引用关联实体的子类时,该名称为[user_address]的错误表已与实体关联

Java 当使用同一联接表引用关联实体的子类时,该名称为[user_address]的错误表已与实体关联,java,hibernate,jpa,Java,Hibernate,Jpa,使用SpringBootStarter,我试图创建一个简单的示例项目,该项目涉及一个具有多个地址字段的用户。我正在试验使用@DiscriminatorColumn和@DiscriminatorValue来区分用户可能拥有的不同类型的地址 以下是我的项目中表格的简化示例: CREATE TABLE user ( id INT AUTO_INCREMENT); CREATE TABLE user_address ( user_id INT, address_id INT); CREATE TABLE

使用SpringBootStarter,我试图创建一个简单的示例项目,该项目涉及一个具有多个地址字段的用户。我正在试验使用@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));
以下是我想参加的课程:

@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
替换
@onetomone
,但仍然不起作用

我希望能够做到这一点的原因是,我正在考虑将地址与其他实体相关联。例如,订单的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
您的错误是:

原因: org.hibernate.boot.spi.InFlightMetadataCollector$DuplicateSecondaryTableException: 名称为[用户地址]的表已与实体关联

您已经放弃了
@继承
注释。 我想所有adress类都使用一个表。因此,您应该明确希望使用
单表
策略来处理OOP->SQL映射。它是默认情况下使用的,但您可以对其进行精确,因为它更具可读性

将其添加到超级类实体的类声明中:
@heritance(策略=heritancetype.SINGLE\u表)

这样:

@Entity
@DiscriminatorColumn(name = "type")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Address {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String type;
}
编辑:

user\u address
用作
user
实体中多个关系中的可联接项。Hibernate给人的印象是它不接受它。

如果使用单一关系,则无法对地址进行分类。

如果可以更改架构,则可以删除联接表并添加fk in地址以指定用户ID。很抱歉,我没有其他线索。

不幸的是,您无法为两个地址类型建立单独的关系,因为纯JPA无法在查询中“区分”连接的结果,也就是说,没有使用鉴别器值进行连接,以仅获取某个关联的特定类型的对象和另一个关联的另一类型的对象。相反,Hibernate有方法来实现这一点,但不符合JPA规范

因此,它工作的唯一方式是允许您与Address对象建立
@OneToMany
关系,作为回报,您可以使用包含 依次是
家庭地址
当前地址
对象

我也有类似的问题。对我来说,唯一的解决办法就是稍微改变一下工作方式(基本上是以一种我不太喜欢的方式,但仅此而已)

基本上,您有4个选项(和几个备选方案):

1-只有一个(
@OneToMany
)关系,请在检索后扫描您的集合以查找类型为
homemaddress
和/或
CurrentAddress
的对象,并将其分配到正确的字段

2-改变遗产的设计方式。在这种情况下,您可以使用Address作为
@MappedSuperclass
,子类作为扩展Address类的实体。这两个类应该映射到两个单独的表中。您不需要联接表。 这就是我前进的方式,即使我不太喜欢它

3-丢弃继承并使用两个单独的表

4-使用hibernate(非jpa)注释


很抱歉,没有粘贴代码,但我无法在此处执行此操作&现在

您是否尝试了该属性

@许多

因为你会把你拥有的存档

A和B,其中A可能包含有 很多孩子在B区,反之亦然


从概念上讲,发货地址与家庭地址相同,与账单地址相同。为什么需要不同的具体实现?您应该在问题中加入错误日志,因为它可能会随着外部主机的出现而消失。共享关系不是JPA规范的一部分。使用它们将是不可移植的,并且是特定于JPA提供商的。FWIWI添加了错误消息并删除了pastebin链接。从概念上讲,地址是相同的,但我希望能够按类型识别它们。我可以将该类型设置为枚举并手动填充该字段,但我想尝试是否可以使用
@DiscriminatorValue
自动填充该类型字段。如果这实际上是可能的,它可以应用于其他概念,如联系方式。只有一个表,其中包含电话号码、电子邮件或社交媒体用户名,并有一个区分它们的类型列。不幸的是,它仍然会产生相同的错误消息。我感谢您为帮助我所做的努力。