Java 如何使用hibernate与现有对象创建组合键对象

Java 如何使用hibernate与现有对象创建组合键对象,java,spring,hibernate,jpa,composite-primary-key,Java,Spring,Hibernate,Jpa,Composite Primary Key,假设我有以下数据库模式 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 AUT

假设我有以下数据库模式

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
    private long id;
    private String name;
    //getters and setters
}
EmployeeTerritoryFunction实体(复合键表)

EmployeeTerrityFunction 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和employee\u territory\u函数列表,但当我首先删除所有现有territory、employee\u territory\u函数并尝试使用现有employee插入时,hibernate无法自动插入或更新employee,自动插入区域,员工区域功能。 低于误差

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 fetch类型替换为EAGER时,我得到了以下错误

Caused by: javax.persistence.EntityNotFoundException: Unable to find com.example.demo.Territory with id 3
hibernate可能会尝试查询Territory表,但当他这样做时,我不会这样做,因为我删除了Territory和EmployeeTerritoryFunction表上的所有数据,并且只有员工现有数据不会被删除


如何修复请?

EmployeeTerrityFunction和EmployeeTerrityFunctionPK两个类中的字段的名称应该完全相同,并且具有您没有的相同类型。试着这样做:

@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 }

}

你可以看看这个答案:谢谢你的回答。根据链接的答案,我应该使用EAGER-oneToMany-fetch类型。但还是有另一个错误。请在我编辑的问题@BrianVosburghThanks@Conrad中查找,但是我如何使用EmployeeTerritoryFunction类型的对象,然后设置Territory和Employee类型的字段?现在我得到了这个异常
DuplicateMappingException:Table[Employee_Territory_function]包含物理列名[Employee_id]由多个逻辑列名引用:[employee_id],[employeeId]
再次更新了我的答案,我希望这一个会有所帮助。现在我完成了问题中的第一次执行,当我将fetchtype设置为EAGER时,Territory将插入,主键由数据库自动生成,但名称的值为空(我将其他属性设置为空)即使我设置了示例插入中所示的值,您能举个例子吗?如果你打字不正确,就很难理解你的问题。
Caused by: javax.persistence.EntityNotFoundException: Unable to find com.example.demo.Territory with id 3
@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 }

}