Проблемы с наследованием в режиме гибернации: аннотации @SecondaryTable

#java #spring #hibernate

#java #spring #гибернация

Вопрос:

У меня есть следующие классы:

// Класс Actor

 @Entity
@Table(name=Actor.TABLE_NAME)  
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="type")
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public abstract class Actor{

    public static final String TABLE_NAME = "actor";

    @Id
    @Column(name="id")
    private String id = IdGenerator.createId();   

    public Actor() { }

    public String getId() { return id;  }
}
  

// Класс компании

 @Entity
@SecondaryTable(name = Company.TABLE_NAME, pkJoinColumns= {@PrimaryKeyJoinColumn(name=Company.PK_NAME)})
@DiscriminatorValue("company")

public class Company extends Actor {

    public static final String TABLE_NAME = "company";
    public static final String PK_NAME = "id";

    // Inherits Id from superclass Actor

    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER)
    @JoinColumn(name="categoryid") 
    private Category category;

    @Column(name = "name", nullable=false)
    @Size(min=2, max=60, message="LATER")
    private String name;

    @Column(name="domainName", nullable=true)
    private String domainName;  

    @Column(name="registrationNumber", nullable=true)
    private String registrationNumber;

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


    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="itemId")
    private Set<Image> logos = new HashSet<>();

    @OneToMany(mappedBy="company", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
    private Set<Branch> branches = new HashSet<>();

    public Company() {}

    public void addBranch(Branch branch) {
        branch.setCompany(this);
        branches.add(branch);
    }

    public void addLogo(Image logo) {

    }

// GETTERS AND SETTERS .......

}
  

// Класс ветви

 @Entity
@Table(name=Branch.TABLE_NAME)
public class Branch {

    public static final String TABLE_NAME = "branch";

    @Id
    @Column(name = "id")
    private String id = IdGenerator.createId();

    @OneToOne(cascade=CascadeType.ALL)
    @JoinColumn(name="address")
    private Address address;

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

    @ManyToOne
    @JoinColumn(name="company")
    private Company company;

    public Branch() {
        this.address.setAddressCategory(AddressCategory.BRANCH); 
    }

// GETTERS AND SETTERS

}
  

// Класс адреса

 @Entity  
@Table(name=Address.TABLE_ADDRESS) 
public class Address {

    public static final String TABLE_ADDRESS = "address";
    @Id
    @Column(name="id")
    private String id = IdGenerator.createId();   

    @Column(name="category", nullable=false)
    private AddressCategory addressCategory;;

    @Column(name="streetname", nullable=true)
    private String streetName;

    @Column(name="number", nullable=true)
    private String number;

    @Column(name="postcode", nullable=true)
    private String postcode;

    @Column(name="city", nullable=true)
    private String city;

    @Column(name="country", nullable=true)
    private String country;

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

    @Embedded
    private EmailAddress email;

    @Column(name="description", nullable=true)
    private String description;

    @ManyToOne
    @JoinColumn(name="actor")
    @NotNull(groups = {Update.class}) 
    @JsonIgnore
    private Actor actor;

    public Address() { }

    public Address(Actor actor) {
        this.actor = actor;
    }

// GETTERS AND SETTERS

}
  

Когда я запускаю приведенный выше код со следующим json от Postman:

 {
    "categoryId": "ee6e75c9-2d1b-41c1-8f12-236fbf907683",
    "name": "McDonalds",
    "domainName": "www.McDonalds.be",
    "registrationNumber": "5555555",
    "description": "Food and Drink"
}
  

Я получаю следующее исключение:

 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Field 'company0_.categoryid' not found in field list
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_151]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_151]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:1.8.0_151]
    at java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:1.8.0_151]
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.44.jar:5.1.44]
    at com.mysql.jdbc.Util.getInstance(Util.java:408) ~[mysql-connector-java-5.1.44.jar:5.1.44]
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:943) ~[mysql-connector-java-5.1.44.jar:5.1.44
...
...
  

Пожалуйста, обратите внимание, что я опустил код контроллера, чтобы сделать сообщение кратким. В приведенном выше исключении говорится об атрибуте categoryid в классе company. Я удалил categoryid, и исключение заменяет categoryid атрибутом description

Я думаю, что проблема связана с аннотацией, использующей вторичные таблицы.

Таблицы следующие:

 CREATE TABLE actor
(
   id    VARCHAR(255)   DEFAULT '' NOT NULL,
   type  VARCHAR(255),
   PRIMARY KEY (id)
)


CREATE TABLE company
(
   id                    VARCHAR(255)   NOT NULL,
   categoryid            VARCHAR(255),
   name                  VARCHAR(255)   NOT NULL,
   `domainName`          VARCHAR(255)   NOT NULL,
   `registrationNumber`  VARCHAR(255),
   description           VARCHAR(255)   NOT NULL,
   PRIMARY KEY (id)
)

CREATE TABLE branch
(
   id         VARCHAR(255)   NOT NULL,
   company    VARCHAR(255),
   address    VARCHAR(255),
   telephone  VARCHAR(255),
   PRIMARY KEY (id)
)

CREATE TABLE address
(
   id           VARCHAR(255)   NOT NULL,
   category     VARCHAR(255),
   actor        VARCHAR(255),
   streetname   VARCHAR(255),
   number       VARCHAR(255),
   postcode     VARCHAR(255),
   city         VARCHAR(255),
   country      VARCHAR(255),
   telephone    VARCHAR(255),
   email        VARCHAR(255),
   description  VARCHAR(255),
   PRIMARY KEY (id)
)
  

Комментарии:

1. Возможно, вам потребуется добавить @Table(имя = Актер. ИМЯ_ТАБЛИЦЫ) также в сущности Company. thoughts-on-java.org /…

Ответ №1:

После некоторых исследований я сам нашел ответ. Поскольку я использую @Secondarytable аннотацию к Company классу и также наследую ее от Actor , я должен указать, в какой таблице должны сохраняться атрибуты Company . Путем добавления «table = ИМЯ_ТАБЛИЦЫ» к каждой @Column аннотации атрибутов Company проблема решена. Без «table = ИМЯ_ТАБЛИЦЫ» внутри @Column Hibernate не будет знать, сохранять ли Company свойства в таблице actor или в таблице company.