【问题标题】:Saving @OneToMany entity along with children (@EmbeddedId with composite foreign key)将 @OneToMany 实体与子实体一起保存(@EmbeddedId 与复合外键)
【发布时间】:2020-02-06 10:24:22
【问题描述】:

我有这些表:

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 个字段组成的复合键
  • 员工的主键由公司的复合键(即外键)和公司特有的另一个字段组成。

基于这个相关问题:

JPA how to make composite Foreign Key part of composite Primary Key

我创建了以下实体:

@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 表,但每当我运行 接下来,我只看到一行被写入公司表 而不是 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?

非常感谢!

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    您正在使用公司存储库保存公司,但公司没有级联注释。

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

    应该是:

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

    【讨论】:

    • 谢谢@Klaas,看起来不错。但是,当我尝试使用不同的tenantId(或不同的 fieldName/id)保存第二家公司+员工时,我遇到了约束违规:Unique index or primary key violation: \"FKCOMPANYFIELDNAME_INDEX_1 ON PUBLIC.COMPANY(FIELDNAME) VALUES ('a-company-field-name', 1)\"; SQL statement:\ninsert into company。这里有什么想法吗?在 Employee 表中,四个字段的组合:tenantId+companyFieldName+companyId+fieldName 应该作为主键,所以我应该可以通过更改其中一个来添加另一个 company+employee。
    • 在这种情况下,员工类中的外键设置不起作用。 docs.oracle.com/javaee/6/api/javax/persistence/EmbeddedId.html 中的示例 2 可能适用于您的情况。
    • 谢谢,原来问题中我的外键是如何定义SQL的,我现在更新了,看起来更好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2021-02-16
    相关资源
    最近更新 更多