【问题标题】:Hibernate refresh in many-to-one relation多对一关系中的休眠刷新
【发布时间】:2017-08-04 13:00:44
【问题描述】:

我有这个 2 域模型:

员工

public class Employee {

    private Long    id; 
    private String  name;
    private String  family;
    private Company company;

    //getter & setter

}

和公司:

公开课公司{

private Long            id; 
private String          name; 
private Set<Employee>   employees;

//getter & setter 

}

Employee 和 Company 是多对一的关系,而从 Company 这边看是一对多的关系。

我在事务中保存了一个公司对象,并在保存该公司的员工后:

@Transactional
puplic Long Save (){
        Company cmp=new Company(); 
        cmp.setName("Oracle");
        session.save(cmp);
        Employee employee=new Employee();
        employee.setName("james");
        employee.setFamily("dep");
        employee.setCompany(cmp);
        cmp.getEmployees();//will raise NullPointerException
        cmp=session.get(cmp.getId());//because of first level cache it doesnt load it 
    }

保存员工后,如果我想从公司获取员工集合,它将引发空指针异常,如果我想加载它,因为一级缓存休眠将不会触及数据库并且员工集仍然空值 。

第一个解决方案是我可以在保存员工后刷新Company对象,但我认为hibernate必须有解决方案。

【问题讨论】:

    标签: java hibernate refresh one-to-many hibernate-mapping


    【解决方案1】:

    您永远不应该使用null 集合,因此您应该将映射更改为:

    private Set<Employee>   employees = new HashSet<>();
    

    这样,您甚至不需要 setter,因为 getter 就足够了。此外,请确保同步双向关联的双方:

    public void addEmployee(Employee employee) {
         employees.add(employee);
         employee.setCompany(this);
    }
    
    public void removeEmployee(Employee employee) {
         employees.remove(employee);
         employee.setCompany(null);
    }
    

    你还需要implement equals and hashCode properly in your child entity classes。

    【讨论】:

    • 记得重写 Employee 的 equals 和 hashCode 方法。您可能已经加载了 Employee 对象的不同实例并且 remove 将不起作用。
    • 我不明白为什么我必须覆盖equals和hashcode
    • 如果您阅读了我提供的那篇文章,您就会明白。这只是为了确保您在所有实体状态转换中提供适当的相等性检查。
    • 所以在代码中,当我保存员工时,我必须在 Company 上调用 addEmployee 方法,当我删除它时调用 remove ?
    • 没错。如果您还需要加载父实体,通常会这样做。
    【解决方案2】:

    查看我的代码,

    在 commit() 之后,事务只有你可以得到持久对象,

    public class Employee {
    
        private Long    id; 
        private String  name;
        private String  family;
    
        @ManyToOne
        @JoinColumn(name = "company_id_fk")
        private Company company;
    
        //getter & setter
    
    }
    
    
    public class Company {
    
        private Long            id; 
        private String          name; 
    
        @OneToMany(mappedBy="company")
        List<Employee> listOfEmployees = new ArrayList<Employee>();
    
        //getter & setter 
    }
    
    
    puplic Long Save (){
    
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try{
            Company cmp=new Company(); 
            cmp.setName("Oracle");
            session.save(cmp);
    
            Employee employee=new Employee();
            employee.setName("james");
            employee.setFamily("dep");
            employee.setCompany(cmp);
            session.save(employee);
    
            transaction.commit();
    
            List<Employee> listOfEmployees = cmp.getListOfEmployees();
            if(listOfEmployees !=null && !listOfEmployees .isEmpty()){
                for(Employee employ:listOfEmployees){
                  //You can wt you want
                }
            }
    
    
        }catch(Exception e){
            transaction.rollback();
        }finally{
            session.close();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-04
      • 2015-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多