Сохранение сущности @OneToMany вместе с дочерними элементами (@EmbeddedId с составным внешним ключом) - PullRequest
1 голос
/ 06 февраля 2020

У меня есть эти таблицы:

CREATE TABLE company (
    id VARCHAR(256) NOT NULL,
    tenantId VARCHAR(256) NOT NULL,
    fieldName VARCHAR(256) NOT NULL,
    PRIMARY KEY (id, tenantId, fieldName)
);

CREATE TABLE employee (
    tenantId VARCHAR(256) NOT NULL,
    companyFieldName VARCHAR(256) NOT NULL,
    companyId VARCHAR(256) NOT NULL,
    fieldName VARCHAR(256) NOT NULL,
    PRIMARY KEY (tenantId, companyFieldName, companyId, fieldName),
    CONSTRAINT fkCompany FOREIGN KEY (tenantId, companyFieldName, companyId) REFERENCES employee (tenantId, fieldName, id)
);
  • В одной компании может быть много сотрудников
  • Первичным ключом компании является составной ключ, состоящий из 3 полей
  • Первичный ключ сотрудника состоит из составного ключа компании (т. Е. Внешнего ключа), а также другого поля, указывающего c для компании.

На основе этого взаимосвязанного вопроса:

JPA, как сделать составной внешний ключ частью составного первичного ключа

Я создал следующие объекты:

@Embeddable
public class CompanyIdentity implements Serializable
{
    @NotBlank
    private String tenantId;

    @NotBlank
    private String fieldName;

    @NotBlank
    private String id;

    //getters, setters, equals and hashcode ommited
}

@Entity
public class Company implements Serializable
{
    @EmbeddedId
    private CompanyIdentity companyIdentity;

    @OneToMany(mappedBy = "company")
    private Set<Employee> employees;

    //getters, setters, equals and hashcode ommited
}

@Embeddable
public class EmployeeIdentity implements Serializable
{
    @NotNull
    private CompanyIdentity companyIdentity;

    // This *not* the fieldName in the CompanyIdentity, this is a property
    // specific to an employee, it just happens to have the same name
    @NotBlank
    private String fieldName; 

    //getters, setters, equals and hashcode ommited
}

public class Employee implements Serializable
{
    @EmbeddedId
    private EmployeeIdentity employeeIdentity;

    @MapsId("companyIdentity")
    @JoinColumns({
        @JoinColumn(name = "tenantId", referencedColumnName = "tenantId"),
        @JoinColumn(name = "companyFieldName", referencedColumnName = "fieldName"),
        @JoinColumn(name = "companyId", referencedColumnName = "id")
    })
    @ManyToOne
    @Cascade(value={org.hibernate.annotations.CascadeType.ALL})
    private Company company;

    //getters, setters, equals and hashcode ommited
}

Я хочу сохранить компанию с одним сотрудником, и пусть он записывает строку в таблицу Company и таблицу Employee, но всякий раз, когда я запускаю следующее, я только вижу, как записывается строка в таблицу Company, а не в таблицу Employee?

Я не уверен если ниже правильный подход или нет, или, может быть, вышеприведенные объекты не верны?

public interface CompanyRepository extends CrudRepository<Company, String> {}
final Company company = new Company();
final CompanyIdentity companyIdentity = new CompanyIdentity("company-tenant-id", "company-field-name", "company-id");

company.setCompanyIdentity(companyIdentity);

final Employee employee = new Employee();

final EmployeeIdentity employeeIdentity = new EmployeeIdentity();
employeeIdentity.setFieldName("employee-field-name");
employeeIdentity.setCompanyIdentity(companyIdentity);

employee.setEmployeeIdentity(employeeIdentity);

employee.setCompany(company);

final Set<Employee> employees = new HashSet<>();
employees.add(employee);

company.setEmployees(employees);

companyRepository.save(company); //only saves company, not employee?

Большое спасибо!

1 Ответ

1 голос
/ 06 февраля 2020

Вы сохраняете компанию с помощью репозитория компании, но у компании нет каскадной аннотации.

@OneToMany(mappedBy = "company")
private Set<Employee> employees;

Должно быть:

@OneToMany(mappedBy = "company")
@Cascade(value={org.hibernate.annotations.CascadeType.ALL})
private Set<Employee> employees;
...