【问题标题】:How to create composite key objects with existing object using hibernate如何使用hibernate创建具有现有对象的复合键对象
【发布时间】:2020-03-19 21:22:54
【问题描述】:

假设我有以下数据库架构

CREATE TABLE employee(
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    hrid VARCHAR (50)
);
CREATE TABLE territory(
    id BIGINT PRIMARY KEY,
    name varchar (50)
);
CREATE TABLE transcode(
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    code VARCHAR (10) NOT NULL
);
create table employee_territory_function(
  employee_id BIGINT NOT NULL,
  territory_id BIGINT NOT NULL,
  transcode_id BIGINT NOT NULL,
  PRIMARY KEY (employee_id,territory_id),
  CONSTRAINT employeeref FOREIGN KEY (employee_id) REFERENCES employee (id),
  CONSTRAINT territoryref FOREIGN KEY (territory_id) REFERENCES territory (id) ,
  CONSTRAINT transcoderef FOREIGN KEY (transcode_id) REFERENCES transcode (id)
);

现在我有以下 JPA 映射实体

员工实体

@Entity
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    private String hrid;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "employee", cascade = CascadeType.ALL)
    private Set<EmployeeTerritoryFunction> employeeTerritoryFunctionList = new HashSet<>();
    //getters and setters
}

领土实体:

@Entity
public class Territory implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;

    // getters and setters for all field

}

转码实体:

@Entity
public class Territory implements Serializable {
    @Id
    private long id;
    private String name;
    //getters and setters
}

EmployeeTerritoryFunction 实体(复合键表)

@Entity
@IdClass(value = EmployeeTerritoryFunctionPK.class)
public class EmployeeTerritoryFunction implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @ManyToOne
    private Employee employee;

    @Id
    @ManyToOne
    private Territory territory;

    @ManyToOne
    @JoinColumn(name = "transcode_id", referencedColumnName = "id")
    private Transcode transcode;
    //getters and setters
}

EmployeeTerritoryFunction pk

public class EmployeeTerritoryFunctionPK implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long employee;
    private Long territory;
    //getters and setters, no args constructor, equals and hashcode
}

样本插入下方

Employee employee = this.employeeRepository.findByHrid("111");
        if (employee == null) {
            employee = new Employee();
            employee.setName("Marie");
            employee.setHrid("333");
        }

        Territory territory = new Territory();
        territory.setId(2L);
        territory.setName("T2");

        Territory territory2 = new Territory();
        territory2.setId(3L);
        territory2.setName("T3");


        Transcode transcode = this.transcodeRepository.findByCode("ASC");
        Transcode transcode2 = this.transcodeRepository.findByCode("CC");


        EmployeeTerritoryFunction employeeTerritoryFunction1 = new EmployeeTerritoryFunction();

        employeeTerritoryFunction1.setTranscode(transcode);
        employeeTerritoryFunction1.setTerritory(territory);
        employeeTerritoryFunction1.setEmployee(employee);
        employee.getEmployeeTerritoryFunctionList().add(employeeTerritoryFunction1);

        EmployeeTerritoryFunction employeeTerritoryFunction2 = new EmployeeTerritoryFunction();
        employeeTerritoryFunction2.setTranscode(transcode2);
        employeeTerritoryFunction2.setTerritory(territory2);
        employeeTerritoryFunction2.setEmployee(employee);
        employee.getEmployeeTerritoryFunctionList().add(employeeTerritoryFunction2);

        employeeRepository.save(employee);

当我只使用新对象运行上面的代码时,我没有问题,因为 hibernate 会自动插入员工、区域和employee_territory_function 列表,但是当我第一次删除所有现有区域时,employee_territory_function 并尝试使用现有员工插入, hibernate 不能自动插入或更新员工、自动插入区域、employee_territory_function。 下面的错误

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.Employee.employeeTerritoryFunctionList, could not initialize proxy - no Session

当我将 oneToMany 提取类型替换为 EAGER 时,出现以下错误

Caused by: javax.persistence.EntityNotFoundException: Unable to find com.example.demo.Territory with id 3

hibernate 尝试查询 Territory 表的接缝,但我不这样做,因为我删除了 Territory 和 EmployeeTerritoryFunction 表上的所有数据,并且只有员工现有数据没有被删除。

请问如何解决?

【问题讨论】:

  • 你可以看看这个答案:stackoverflow.com/a/22822283/1566345
  • 感谢您的回复。根据链接的答案,我应该使用 EAGER oneToMany 获取类型。但仍然出现另一个错误。请在我编辑的问题中找到@BrianVosburgh

标签: java spring hibernate jpa composite-primary-key


【解决方案1】:

EmployeeTerritoryFunction 和 EmployeeTerritoryFunctionPK 两个类中的字段应命名完全相同,并且具有您没有的相同类型。试试这样:

@Entity
@IdClass(EmployeeTerritoryFunctionPK.class)
public class EmployeeTerritoryFunction implements Serializable {

    @Id
    @ManyToOne
    private Employee employee;

    @Id
    @ManyToOne
    private Territory territory;
}

public class EmployeeTerritoryFunctionPK implements Serializable {
    private Employee employee;
    private Territory territory;

    public int hashCode() { //TODO }
    public boolean equals(Object obj) { //TODO }

}

【讨论】:

  • 谢谢@Conrad,但是我怎样才能使用 EmployeeTerritoryFunction 类型的对象,然后设置 Territory 和 Employee 类型的字段?
  • 现在我得到了这个异常DuplicateMappingException: Table [employee_territory_function] contains physical column name [employee_id] referred to by multiple logical column names: [employee_id], [employeeId]
  • 再次更新了我的答案,希望对您有所帮助。
  • 现在我在我的问题中进行了第一次执行,当我将 fetchtype 设置为 EAGER 时,Territory 会插入主键,由数据库自动生成,但名称的空值(我来宾其他属性)即使我设置我的示例插入中显示的值。
  • 你能举个例子吗?当你没有正确输入时,很难理解你的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 2015-09-11
  • 1970-01-01
相关资源
最近更新 更多