2011-03-29 9 views
0

注意孩子的實體:不能刪除具有收藏與休眠

這是一個croass後:hibernate forum

因爲我沒有答案,所以我在這裏問,看看我是否能得到一些幫幫我。 :)

如果這是在這裏解決,我會發布在休眠論壇的答案。 :)


在我的應用程序中,我有一些實體擁有一些集合,當我不知道刪除它們。

這是我eneity的核心代碼:

代碼:

@Entity 
@Table(
     name = "t_task") 
public class Task { 
    private int   id; 
    private List<TaskStep> steps = new ArrayList<TaskStep>(); 

    public Task() { 
     this.createTime = new Date(); 
    } 
    public Task(String name) { 
     this(); 
     this.name = name; 
    } 
    @Id 
    @GeneratedValue 
    public int getId() { 
     return id; 
    } 
    @OneToMany(
     cascade = CascadeType.ALL) 
    @JoinColumn(
     name = "task_id", 
     nullable = false) 
    @LazyCollection(LazyCollectionOption.FALSE) 
    @IndexColumn(
     name = "position") 
    public List<TaskStep> getSteps() { 
     return steps; 
    } 
    // domain method 
    public void addSteps(TaskStep ts) { 
     steps.add(ts); 
     ts.setTask(this); 
    } 

    public void removeStep(TaskStep ts) { 
     steps.remove(ts); 
    } 

    // setter 
    public void setId(int id) { 
     this.id = id; 
    } 

    public void setSteps(List<TaskStep> steps) { 
     this.steps = steps; 
     for (TaskStep st : steps) { 
     st.setTask(this); 
     } 
    } 

} 


//TaskStep: 

@Entity 
@Table(
     name = "t_taskstep") 
public class TaskStep { 
    private int   id; 
    private List<Operator> operator = new ArrayList<Operator>(); 
    private Task   task; 

    public TaskStep() {} 

    @Id 
    @GeneratedValue 
    public int getId() { 
     return id; 
    } 

    @ManyToMany(
     cascade = CascadeType.ALL) 
    @LazyCollection(LazyCollectionOption.FALSE) 
    public List<Operator> getOperator() { 
     return operator; 
    } 

    @ManyToOne 
    @JoinColumn(
     name = "task_id", 
     nullable = false, 
     updatable = false, 
     insertable = false) 
    public Task getTask() { 
     return task; 
    } 
    // domain method start 
    public void addOperator(Operator op) { 
     operator.add(op); 
    } 
    // setter 
    public void setId(int id) { 
     this.id = id; 
    } 

    public void setOperator(List<Operator> operator) { 
     this.operator = operator; 
    } 

    public void setTask(Task task) { 
     this.task = task; 
    } 
} 

//Operator: 
@Entity 
@Table(
     name = "t_operator") 
public class Operator { 
    private int   id; 
    private List<TaskStep> steps = new ArrayList<TaskStep>(); 

    public Operator() {} 
    @Id 
    @GeneratedValue 
    public int getId() { 
     return id; 
    } 
    // //setter 
    public void setId(int id) { 
     this.id = id; 
    } 

    public void setSteps(List<TaskStep> steps) { 
     this.steps = steps; 
    } 
    @ManyToMany(
     mappedBy = "operator") 
    public List<TaskStep> getSteps() { 
     return steps; 
    } 
} 

在db,有 「t_task」, 「t_operator」, 「t_step」, 「t_step_operator」 的表格。

我使用這種方式刪除任務: 代碼: taskDao.delTask​​ById(5);

這是道:

代碼:

public void delTaskById(int id) { 
     Task t = queryTaskById(id); 
     Session sess = factory.getCurrentSession(); 
     try { 
     sess.beginTransaction(); 
     sess.delete(t); // 1) 
     sess.flush(); 
     sess.getTransaction().commit(); 
     } catch (HibernateException e) { 
     sess.getTransaction().rollback(); 
     } 
    } 

我得到了一個錯誤,說:「不能刪除或更新父行......」。

然後我試圖使用repalce的

sess.delete(t) 

sess.createQuery("delete from Task t where t.id="+id).executeUpdate() 

我現在得到的錯誤,但任務沒有實際刪除。

我已經在映射中設置了級聯。例如,對於任務對象中的任務測試,我設置了cascade.type = all,所以我認爲當hibernate嘗試刪除任務時,它應該刪除其實現的任務步驟,並且當它嘗試刪除任務步驟對象時,它會發現「t_step_t_operator」表引用了「t_step」中的id,因此我還爲任務類中的「step」字段設置了「cascade = all」。 但似乎發生了什麼事情並不是我認爲的......

問題是什麼?我瘋了!

任何人都可以幫我一個忙嗎?

BWT,級聯是什麼意思?

例如: 在TaskStep calss中,我有一個操作符列表;

//Class:TaskStep. 
    @ManyToMany(
     cascade = CascadeType.ALL) 
    @LazyCollection(LazyCollectionOption.FALSE) 
    public List<Operator> getOperator() { 
     return operator; 
    } 

在上述〔實施例,我設置級聯= ALL,這是否意味着無論什麼操作(豆腐)的TaskStep,它會做同樣的操作來Opeartors?

回答

1

如果你想(模擬)沒有連接表的雙向關係,你必須這樣做,通過創建兩個單向關係,並通知Hibernate有關它們之間的關係 - 通過使用mappedBy,如JB Nizet所說,還可以保留其他(@ManyToOne)映射

@JoinColumn可用於例如如果您只想映射@OneToMay一側一個關係,但仍然不想要一個連接表 - 你會指出應該使用的其他表中的列,通常單向引用不會影響被引用的表,而是使用連接表。由於默認情況下PK(id)用於雙向關係中的FK約束(t_taskstep.task_id列將具有FK約束至t_task.id)

級聯屬性將導致Create /刪除操作(更新由EntityManager/Session隱式處理)擁有實體,以級聯到(在您的情況下)集合中的所有實體。因此,對Task執行刪除操作也會導致刪除步驟Collection中的所有TaskSteps實例,並且還會刪除TaskStep中的Operator操作符。勇敢的,但可能失敗,因爲你有@ManyToMany關係 - 其他TaskStep實例可能引用你的刪除層疊到的操作符。通常只能級聯保存更新(或組件/嵌入式中的映射關係)並手動刪除。如果您確定您的集合是唯一引用另一個實體的集合,那麼您可以使用ALL以及DELETE-ORPHAN,從而只需將它們從集合中刪除即可刪除引用的實體。

@IndexColumn用於如果你想記住列表中的對象的順序。如果你不在意,跳過它,你的關係將有Bag語義(無序,允許重複)。通常情況下,您不希望在集合中看到重複內容,因此應該使用集合集合。

很長的答案,對不起。應該簡單地提供代碼。

+0

我測試過了,如果我只在映射中使用mappedBy,那麼位置就不會被設置,所以我必須定義兩次「joinColumn」,看看這個:http://opensource.atlassian.com/projects/hibernate/browse/HHH-4390。順便說一句,從你的回答中,我對雙向關係和雙向引用感到困惑。在我的例子中,task和tasktep都是引用另一個,這是雙向引用,但是在這種訴訟中什麼是關係?bi或un? – hguser 2011-03-30 01:14:15

1

您在Task和TaskStep之間的關係被映射兩次:一次在任務中,一次在TaskStep中。在任務@JoinColumn應該消失,@OneToMany應該有一個「的mappedBy」屬性:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "task") 
@LazyCollection(LazyCollectionOption.FALSE) 
@IndexColumn(name = "position") 
public List<TaskStep> getSteps() { 
    return steps; 
} 
+0

是的,你是對的,但是如果我只是設置關係一次,任務步驟中的位置列不能很好地工作,所以我將它們設置了兩次(一個任務的任務步驟的順序在我的應用程序中被請求。 – hguser 2011-03-29 12:20:05

+0

我認爲當你添加一個mappedBy時,位置管理不能很好地工作,因爲當你向一個任務添加一個步驟時,你忘記了初始化反向關係,這是你的責任,確保雙方都被修改。請參閱http://stackoverflow.com/questions/5460573/hibernate-bidirectional-manytoone-updating-the-not-owning-side-not-working/5460743#5460743。被映射一次,而不是兩次 – 2011-03-29 12:39:01

+0

感謝您的關注,在我的任務中,當我添加一個任務步時,我會更新任務步的引用,如下所示:「public void addSteps(TaskStep ts){ steps.add(ts); ts.setTask(this); } 「所以,我想我已經初始化了這個關係,順便說一句,這是我不能刪除任務對象的原因嗎?從昨天開始,當我沒有在taskStep中添加」indexColum「時,我也不能刪除它。 – hguser 2011-03-29 12:44:36