Hibernate DetachedQuery 和 Spring 的 HibernateTemplate with Restriction 给出错误结果

Posted

技术标签:

【中文标题】Hibernate DetachedQuery 和 Spring 的 HibernateTemplate with Restriction 给出错误结果【英文标题】:Hibernate DetachedQuery and Spring's HibernateTemplate with Restriction giving wrong results 【发布时间】:2015-03-13 02:38:47 【问题描述】:

我的数据结构是这样的

Department  
     -> Employees    
        -> Gender  
        -> CityID -> Cities  
                          ->CityID  
                          ->CountryID -> Countries   
                                           -> CountryID

部门类:

public class Department   
@OneToMany(mappedBy = "departmentid", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Employee> employees = new HashSet<>();  

我这样构建标准:

DetachedCriteria criteria = DetachedCriteria.forClass(Department.class);       
DetachedCriteria detlCrit = criteria.createCriteria("employees");
 detlCrit.add(Restrictions.eq("gender", "MALE"));  
 detlCrit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

我有 1 个部门,2 名员工(1 名男性,1 名女性)。 当我执行此标准时,我期望 Hibernate 构建一个“部门” 对象、一个“员工”对象以及城市、国家/地区等,

但我得到的是 1 个部门,2 个员工。

当我在日志中看到 Hibernate 执行的查询时,它显示了两个查询 第一个查询:

Select * from Department, Employee  
     Left outer join City on Employee.cityID = City.cityID  
     Left outer join Country on City.countryID = City.countryID  
     Where Employee.DeptID = Department.DeptID  
      AND  Employee.Gender = 'MALE';  

第二次查询:

Select * from Employee  
     Left outer join City on Employee.cityID = City.cityID  
     Left outer join Country on City.countryID = City.countryID  
     Where Employee.DeptID = Department.DeptID; 

第二次查询错误,没有对 Gender='MALE' 应用限制;

我做错了什么?有什么建议么?如何解决这个问题?

抱歉,查询可能不完全正确,但您明白了。 需要更多细节请询问,我可以提供。

提前谢谢..

【问题讨论】:

能否分享一下使用DetachedCriteria执行查询的代码。 当您说返回两个员工对象时,您的意思是两个 MALE 对象;还是男性和女性? @Mithun,MALE 和 FEMALE 两条记录。限制失败。我只期待男性员工记录。 如果我更改为将 HQL 与 getHibernateTemplate().findByNamedParam(query, params, values) 一起使用,它可以工作,不会得到不需要的 Employee 记录(并且它执行一个 sql 查询而不是两个)。如何使用 Criteria 使其工作? 【参考方案1】:

试试这个,使用 SessionFactory。

@Autowired
private SessionFactory sessionFactory;

Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Department.class);

criteria.add(Restrictions.eq("gender", "MALE"));

希望我有用。

【讨论】:

@OneToMany(mappedBy = "departmentid", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private Set employees = new HashSet(); @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @Fetch(FetchMode.SELECT) @JoinColumn(name = "DepartmentId") @LazyCollection(LazyCollectionOption.FALSE) 私有集 = 新哈希集(); 感谢您调查我的问题。首先“性别”是员工(子)表中的字段,因此添加了这样的限制:DetachedCriteria criteria = DetachedCriteria.forClass(Department.class);DetachedCriteria detlCrit = criteria.createCriteria("employees");detlCrit.add(Restrictions.eq("gender", "MALE"));部门类有:@OneToMany(mappedBy = "departmentid", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private Set employees = new HashSet();第二:我想使用 DetachedCriteria 而不是 Criteria。 我不能使用 SessionFactory,因为我在项目中使用 org.springframework.orm.hibernate3.HibernateTemplate 作为标准。 可以像HibernateTemplate(SessionFactory sessionFactory)一样在org.springframework.orm.hibernate3.HibernateTemplate中使用SessionFactory作为Constructor,然后新建一个HibernateTemplate实例。【参考方案2】:

第一个查询是选择 Department 实体,并按照您在 where 子句中指定的方式应用过滤。

但是你不能截断关联,你总是必须急切地或懒惰地获取它们。这是因为当flushing back 加载的部门实体和可能cascading 员工状态返回数据库时,Hibernate 必须保持一致性保证。

第二个查询很可能是因为您在员工集合中使用了FetchType.EAGER:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "department", orphanRemoval = true)
private List<Employee> employees = new ArrayList<>();

获取部门后,也会急切地获取员工集合。

尝试使用类似于此的 HQL 查询:

select distinct d
from Department d
left join fetch d.employees e
where e.gender = :gender

【讨论】:

我尝试了 orphanRemoval 和更改为 FetchType.LAZY 仍然没有解决。当我使用 LAZY 初始化时,我收到错误 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: xxxx.employees, no session or session was closed 但除非绝对必要,否则我不想使用 HQL,因为我在项目中使用 Criterias 作为标准。 先试试看能不能解决问题,然后我们也可以把它变成Criteria。 好的,我尝试使用 HQL 和 getHibernateTemplate().findByNamedParam(query, params, values),它可以工作。现在我没有得到不需要的记录(它执行一个 sql 查询而不是两个)。但是 getHibernateTemplate.findByCriteria() 有什么问题,如何让它工作?

以上是关于Hibernate DetachedQuery 和 Spring 的 HibernateTemplate with Restriction 给出错误结果的主要内容,如果未能解决你的问题,请参考以下文章

使用 hibernate、hibernate 注释和 ehcache 的 Maven 依赖项是啥?

hibernate和ibatis对比

Hibernate 和 Hibernate JPA 的区别

hibernate里‘query’和‘ Criteria’分别啥时候用

mybatis和hibernate的区别

hibernate jpa 报错