JPA / Hibernate жалуется на дублирование сопоставления при наследовании подкласса - PullRequest
0 голосов
/ 14 июля 2020

Java 8 и MySQL здесь, возникают некоторые проблемы с получением проверки схемы JPA / Hibernate, работающей с моей моделью наследования объектов. У меня Hibernate установлен в «режим проверки» (то есть он должен проверять только мои Java классы и их аннотации JPA / Hibernate по существующей структуре БД).

Мои Java классы:

// All my Java entities extend BaseEntity which just contains a few fields that
// all my DB tables will also have.
@MappedSuperclass
@Data
@EqualsAndHashCode(callSuper=false)
public abstract class BaseEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String refId;

}

// Base class for several Org subclasses. I would like these subclasses to all share
// the same "organizations" table under the hood
@Entity
@Table(name = "organizations")
@AttributeOverrides({
    @AttributeOverride(name = "id", column = @Column(name = "organization_id")),
    @AttributeOverride(name = "refId", column = @Column(name = "organization_ref_id"))
})
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="organization_type", discriminatorType = DiscriminatorType.STRING)
@Data
@EqualsAndHashCode(callSuper=false)
public class Organization extends BaseEntity {

    @Enumerated(EnumType.STRING)
    @Column(name = "organization_type")
    private OrgType type;

    @Column(name = "organization_name")
    private String name;

    @Column(name = "organization_slug")
    private String slug;

    @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "organization_address_id", referencedColumnName = "address_id")
    private Address address;

    @Column(name = "organization_website")
    private String website;

    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinTable(
        name="organizational_contacts",
        joinColumns={
            @JoinColumn(name="organization_id")
        },
        inverseJoinColumns= {
            @JoinColumn(name = "contact_id")
        }
    )
    private Set<Contact> keyContacts;

    @Column(name = "organization_phone")
    private String phone;

    @Column(name = "organization_domain_name")
    private String domainName;

    @Column(name = "organization_preferred_locale")
    private String preferredLocale;

}

@Entity(name = "Vendor")
@DiscriminatorValue("VENDOR")
@Data
@EqualsAndHashCode(callSuper=false)
public class Vendor extends Organization {

    @Column(name = "organization_vendor_naics_code")
    private String naicsCode;

}

А вот моя схема БД:

CREATE TABLE IF NOT EXISTS organizations (
    organization_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
    organization_ref_id VARCHAR(36) NOT NULL,
    organization_type VARCHAR(50) NOT NULL,
    organization_name VARCHAR(100) NOT NULL,
    organization_slug VARCHAR(100) NOT NULL,
    organization_address_id BIGINT UNSIGNED NOT NULL,
    organization_website VARCHAR(250) NOT NULL,
    organization_phone  VARCHAR(25) NOT NULL,
    organization_domain_name VARCHAR(250) NOT NULL,
    organization_preferred_locale VARCHAR(25) NOT NULL,

    -- subclass fields; must ALL be nullable
    organization_vendor_naics_code VARCHAR(6),
    organization_purchaser_country VARCHAR(3),

    CONSTRAINT pk_organizations PRIMARY KEY (organization_id),
    CONSTRAINT fk_organizations_address_id FOREIGN KEY (organization_address_id) REFERENCES addresses (address_id),

    INDEX idx_organizations_organization_ref_id (organization_ref_id),
    INDEX idx_organizations_organization_slug (organization_slug),
    INDEX idx_organizations_organization_domain_name (organization_domain_name),

    CONSTRAINT uc_organizations_organization_ref_id UNIQUE (organization_ref_id),
    CONSTRAINT uc_organizations_organization_slug UNIQUE (organization_slug),
    CONSTRAINT uc_organizations_organization_domain_name UNIQUE (organization_domain_name)
);

Когда я запускаю свое приложение, я получаю:

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.example.myapp.domain.entities.orgs.Vendor column: organization_type (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:862)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:880)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:902)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:634)
    at org.hibernate.mapping.SingleTableSubclass.validate(SingleTableSubclass.java:54)
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:351)

По словам богов Google, это исключение возникает когда два класса пытаются сопоставить один и тот же столбец, но это то, что я хочу, верно ?! Я хочу, чтобы было два подкласса Organization, каждый из которых имеет одну и ту же таблицу organizations (следовательно, стратегию SINGLE_TABLE), и я хочу, чтобы перечисление / строка Organization#type : OrgType было дискриминатором, сообщающим JPA / Hibernate, какой подкласс мы иметь дело с!

Кто-нибудь может заметить, где я ошибаюсь?

1 Ответ

1 голос
/ 14 июля 2020
  • Обновите поле type до
    @Enumerated(EnumType.STRING)
    @Column(name = "organization_type", insertable = false, updatable = false)
    private OrgType type;
  • вы не можете установить значение для поля type, спящий режим автоматически заполнит значение для него на основе @DiscriminatorValue в каждом подклассе, например VENDOR et c. Но поскольку это поле установлено спящим режимом, вы можете прочитать его
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...