我正在编写一个简单的Spring Data JPA应用程序。我使用MySQL数据库。有两个简单的表格:
- 部门
- 员工
每个员工都在某个部门工作(employee.department_id(。
@Entity
public class Department {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@Basic(fetch = FetchType.LAZY)
@OneToMany(mappedBy = "department")
List<Employee> employees;
}
@Entity
public class Employee {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@ManyToOne
@JoinColumn
private Department department;
}
@Repository
public interface DepartmentRepository extends JpaRepository<Department, Long> {
@Query("FROM Department dep JOIN FETCH dep.employees emp WHERE dep = emp.department")
List<Department> getAll();
}
方法getAll
返回一个具有重复部门的列表(每个部门的重复次数与该部门中的员工数量相同(。
问题1:我是否认为这是一个与Spring Data JPA无关的功能,而是与Hibernate有关的功能
问题2:修复它的最佳方法是什么?(我发现了至少两种方法:1(使用Set<Department> getAll();
2(在@Query
注释中使用"SELECT DISTINCT dep"
(
FROM Department dep JOIN FETCH dep.employees emp
表达式生成本机查询,返回纯结果Department-Employee
。每个Department
将被返回dep.employees.size()
次。这是JPA提供者预期的行为(在您的案例中为Hibernate
(。
使用distinct
来消除重复似乎是一个不错的选择。CCD_ 11作为查询结果使得不可能得到有序的结果。
您可能希望使用LEFT JOIN FETCH
和DISTINCT
。普通JOIN FETCH
使用内部联接,因此查询不会返回没有任何员工的部门。LEFT JOIN FETCH使用外部联接。
我不确定是否在这里使用@Query
。如果通过注释@OneToMany
和@ManyToOne
映射这两个实体,则此联接是多余的。第二个时刻,为什么@Basic(fetch = FetchType.LAZY)
在这里?也许你应该在@OneToMany
中设置惰性初始化?看看这个资源,我希望你会发现它对有用
据我所知,在您提到的用例中,您不需要定义自己的方法,而是使用repository.findAll
,它继承自PagingAndSortingRepository
,它扩展了CrudRepository
,并由SimpleJpaRepository
实现。参见此处
因此,只需将存储库界面留空,如下所示,
@Repository
public interface DepartmentRepository extends JpaRepository<Department, Long> {
}
然后注入并在任何需要的地方使用,例如使用DepartmentService
public interface DepartmentService {
List<Link> getAll();
}
@Component
public class DepartmentServiceImpl implements DepartmentService {
private final DepartmentRepository repository;
// dependency injection via constructor
@Autowired
public DepartmentServiceImpl(DepartmentRepository repository) {
this.repository = repository;
}
@Override
public List<Department> getAll() {
return repository.findAll();
}
}