1

Lets say I have the following database schema

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)
);

Now I have the following JPA mapped entities

Employee entity

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

Territory entity:

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

    // getters and setters for all field

}

Transcode Entity:

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

EmployeeTerritoryFunction entity (composite key table)

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

Below sample insertion

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);

when I run above code with only new objects, I have no issue because hibernate automatically insert the employee, the territory and the list of employee_territory_function but when I first delete all existing territory, employee_territory_function and try to insert using an existing employee, hibernate is not able auto insert or update employee, auto insert in territory, employee_territory_function. Below the error

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

When I replace oneToMany fetch type to EAGER, I got below error

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

It seams that hibernate try to query Territory table but I do not when him to do that because I remove all data on Territory and EmployeeTerritoryFunction table and only employee existing data is not removed.

How to fixe please ?

1 Answers1

0

Fields in both classes EmployeeTerritoryFunction and EmployeeTerritoryFunctionPK should be named exactly same and have same types which you don't have. Try like this:

@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
  • 536
  • 5
  • 13
  • Thanks @Conrad but how can I then use an object of Type EmployeeTerritoryFunction and then set field of type Territory and Employee? – Jean-Pascal MEWENEMESSE Nov 25 '19 at 00:05
  • Now I got this exception `DuplicateMappingException: Table [employee_territory_function] contains physical column name [employee_id] referred to by multiple logical column names: [employee_id], [employeeId]` – Jean-Pascal MEWENEMESSE Nov 25 '19 at 10:19
  • Updated my answer again, I hope this one will help. – Conrad Nov 25 '19 at 11:17
  • Now I guet the first exection in my question and when I set fetchtype to EAGER, Territory is insert with it primary key autogenerate by database but null values for name (I guest other properties) even when I set the value as shown in my sample insertion. – Jean-Pascal MEWENEMESSE Nov 25 '19 at 12:16
  • Can you give an example? It is hard to understand your problem when you dont type correctly. – Conrad Nov 25 '19 at 13:02
  • The issue is that I cannot insert into `employee_territory_function` and `territory` using an existing `employee`. I got `LazyInitializationException`. Please take a look at sample code in question or the sample project on this link github.com/pascalito007/demo.git Thanks @Conrad – Jean-Pascal MEWENEMESSE Nov 26 '19 at 15:08
  • Example from my answer is working. "could not initialize proxy - no Session" means that transactional didn't started session. I have looked at your code and you're using @Transactional wrong cause you've put it on method in class com.example.demo.DemoApplication, which is not spring bean. Move com.example.demo.DemoApplication#manageData to spring bean ( class with annotation @Component/@Service ) and it'll work. – Conrad Nov 26 '19 at 23:57