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.