2011-08-18 68 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'。 –