简体   繁体   中英

Hibernate and Criteria Api generates wrong Join condition

I got following tables. Lets ignore the fact that the relation is done wrong here. I cannot change that. Each company can have multiple employes and each employe belongs to only one company.

Table: Company

ID EMPLOYE_ID
10 100

Table: Employe

ID NAME
100 (Same as EMPLOYE_ID) John

Now i want to create a relation @OneToMany between Company -> Employe. My entities look as follow

class Company {
  @Id
  @Column(name = "id", unique = true, nullable = false)
  private String id;

  @OneToMany(fetch = FetchType.LAZY)
  @JoinColumn(name = "EMPLOYE_ID", referencedColumnName = "ID")
  private Set<Employe> employees;
  
}

No matter if i try to create a uniderectional, or biderection relationship by adding also @ManyToOne on my Employe class, when using Criteria api to select all Company entities and their Employes i always end up with a wrong generated SQL query at the point where it joines the tables. The above relation for example creates following:

FROM company company0
INNER JOIN employe employe0 ON company0.id = employe0.employe_id

I tried several approaches, but i end up almost with the same error. It tries either to access a column which does not exist on the table, or joins wrong columns (eg id = id). Or by the following exception

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.Employe column: id (should be mapped with insert="false" update="false")"}}

What is a simple approach to create a bidrectional relation with the above table structure?

Note : I finally ended up changing the DB schema. Still, it would be interesting if someone could provide an answer for such a case, even if it is based on a not well formed

The central problem is that the described table structures do not allow a 1:n relationship from Company to Employee. According to the table design (especially the design of PKs) above, a company can only have one employee.

However, if the DB design cannot be changed, the following approach using the JoinColumnOrFormula annotation may lead to partial success.

The @JoinColumnOrFormula annotation is used to customize the join between a child Foreign Key and a parent row Primary Key when we need to take into consideration a column value as well as a @JoinFormula.

See https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#associations-JoinColumnOrFormula for details.

More concretely with these Entities

@Entity
@Table(name="t_company")
public class Company {
    @Id
    @Column(name="id")
    private Integer id;
    @Column(name="employee_id")
    private Integer employeeId;
    @OneToMany(mappedBy = "company")
    private List<Employee> employees;    

    // ..
}

@Entity
@Table(name = "t_employee")
public class Employee {
    @Id
    @Column(name = "id")
    private Integer id;
    @Column(name = "name")
    private String name;
    @ManyToOne
    @JoinColumnOrFormula( column =
        @JoinColumn(
                name = "id",
                referencedColumnName = "employee_id",
                insertable = false,
                updatable = false
        )
    )
    private Company company;

    // ..
}

and this custom repository

@Repository
public class EmployeeRepository {

    @Autowired
    EntityManager entityManager;

    List<Employee> findAll() {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);

        Root<Employee> root = cq.from(Employee.class);
        Join<Employee, Company> joinCompany = root.join("company");

        TypedQuery<Employee> query = entityManager.createQuery(cq);
        return query.getResultList();
    }

}

you get the following query:

  select
        employee0_.id as id1_1_,
        employee0_.name as name2_1_
   from t_employee employee0_
   inner join t_company company1_ on employee0_.id=company1_.employee

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM