2011-08-18 42 views
1

我遇到了我的Hibernate映射问题。 我有我的实体之间的多对一映射。 在我的Oracle数据库的两个表如下...Java休眠多对一问题

Employee                                      
-------------------------- 
EMPLOYEE_ID 
EMPLOYEE_FIRST_NAME 
EMPLOYEE_LAST_NAME 
HEALTH_PLAN_ID                                     
Health_Plan 
------------------= 
HEALTH_PLAN_ID 
HEALTH_PLAN_NAME 
HEALTH_PLAN_RATE 

我的映射......

@Entity 
@Table(name = "Employee") 
@SequenceGenerator(name = "employee_seq", sequenceName = "employee_seq") 
public class Employee { 
    private int employeeId; 
    private String firstName; 
    private String lastName; 
    private HealthPlan plan; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "employee_seq") 
    @Column(name = "employee_id", nullable = false) 
    public int getEmployeeId() { 
     return employeeId; 
    } 
    @Column(name = "employee_first_name", nullable = false) 
    public String getFirstName() { 
     return firstName; 
    } 
    @Column(name = "employee_last_name", nullable = false) 
    public String getLastName() { 
     return lastName; 
    } 
    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "HEALTH_PLAN_ID") 
    public HealthPlan getPlan() { 
     return plan; 
    } 
} 

@Entity 
@Table(name = "HEALTH_PLAN") 
@SequenceGenerator(name = "HEALTH_PLAN_SEQ", sequenceName = "HEALTH_PLAN_SEQ") 
public class HealthPlan { 
    private int healthPlanId; 
    private String healthPlanName; 
    private double healthPlanRate; 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HEALTH_PLAN_SEQ") 
    @Column(nullable = false, name = "HEALTH_PLAN_ID") 
    public int getHealthPlanId() { 
     return healthPlanId; 
    } 
    @Column(nullable = false, name = "HEALTH_PLAN_NAME", unique = true) 
    public String getHealthPlanName() { 
     return healthPlanName; 
    } 
    @Column(nullable = false, name = "HEALTH_PLAN_RATE") 
    public double getHealthPlanRate() { 
     return healthPlanRate; 
    } 
} 

当我运行下面的代码....

public static void main(String[] args) throws SQLException {   
     HealthPlanDaoImpl healthDao = new HealthPlanDaoImpl(); 
     EmployeeDaoImpl empDao = new EmployeeDaoImpl(); 

     HealthPlan plan = new HealthPlan(); 
     plan.setHealthPlanName("PLAN B"); 
     plan.setHealthPlanRate(5.0); 

     Employee emp = new Employee(); 
     emp.setPlan(plan); 
     emp.setFirstName("Jane"); 
     emp.setLastName("Doe"); 
     boolean isSuccess = empDao.addEmployee(emp); 
     System.out.println(isSuccess); 

    } 
public class EmployeeDaoImpl{ 
    public boolean addEmployee(Employee emp) { 
     boolean bolReturn = true; 

     Session session = HibernateUtil.beginTransaction(); 
     try { 
      session.save(emp); 
      HibernateUtil.commitTransaction(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      bolReturn = false; 
      HibernateUtil.rollbackTransaction(); 
     } 
     return bolReturn; 
    } 
} 

在Health_Plan表中,HEALTH_PLAN_ID = 3(这是正确的!) 在Employee Table中,HEALTH_PLAN_ID = 1850(这个值来自哪里?我预计这也是3。)

我尝试了几次,我注意到在员工表HEALTH_PLAN_ID只增加了300. 我想我已经设置了级联选项。

任何提示?

回答

1
HealthPlan plan = new HealthPlan(); 
plan.setHealthPlanName("PLAN B"); 
plan.setHealthPlanRate(5.0); 

Employee emp = new Employee(); 
emp.setPlan(plan); 
emp.setFirstName("Jane"); 
emp.setLastName("Doe"); 

为创建的每个Employee实例创建一个新的HealthPlan实例。原始HealthPlan实例未用于新的Employee与现有HealthPlan之间的新映射。如果您查询现有的HealthPlan实例,然后将其设置为每个Employee,您会发现健康计划ID在各个对象之间将保持一致。

HEALTH_PLAN_ID值的差异可归因于您的测试代码的上述行为。此外,序列分配大小已经增加了50,这是默认值,并且您碰巧看到了六个连续序列增量操作的结果。请注意,Hibernate将更新不同事务中的序列,因此即使您回滚当前事务,您也会发现序列值将递增。

在另一个笔记上,我建议不要使用与ALL的CascadeType值之间的单向@ManyToOne关系。如果一个Employee被删除,或者就此而言,允许更新来自员工的HealthPlan实例以传播合并事件,是否真的要删除所有Employee实例中的HealthPlan

+0

我想我有关于HealthPlan的第一点。我认为当我拯救我的员工实例时,健康计划应该存在。第二点,理想的CascadeType Option应该是什么?谢谢 –

+0

@Mark,我建议使用双向的'@ ManyToOne'(通过在'HealthPlan'中指定'@ OneToMany' Set'或'List'' Employee'实例)而不是单向的'@ ManyToOne';那么你应该在'HealthPlan'的反义'@ OneToMany'声明中指定级联类型。然后,您可以在'@ OneToMany'注释中指定ALL的级联类型,而不是'@ ManyToOne'注释。 –

+0

这是我在努力理解的Hibernate中的一个概念。我真的需要在实体的两端配置关联吗?我的意思是,当我执行查询时,与具有特定健康计划的员工实体一起执行它是不合逻辑的。或者,我应该与健康计划实体合作并检索具有此健康计划的员工名单?另外,就性能而言,哪一个更快?谢谢你的耐心。 –

0

我不知道问题的确切原因,但我可以马上看到代码的一些问题。 1.在健康计划表中,注释表示GenerationType.SEQUENCE,在员工表中它表示GenerationType.AUTO 2.在员工表中@Column(name =“employee_id”,可为空= false)。 employee_id既不是实体类中变量的名称,也不是实际列的名称。该实体类中的三列有这个问题。

也许如果你解决这个问题,它可以解决你的问题?

+1

“@ Column”注释中的名称代表表列名称而不是实体属性名称(这是毫无意义的)。此外,默认情况下,Oracle列名是不区分大小写的,除非它们被引用,所以'@Column(name =“employee_id”...'实际上映射到'Employee.EMPLOYEE_ID'。 –