2016-10-04 58 views
0

我有一個實體類,其中每個實例可以具有相同類型的父級。Java JpaRepository @Query加入自己的表

現在我想能夠刪除父對象,並在該過程中刪除它的所有子對象。我無法通過級聯類型來完成,因此我在我的JPA存儲庫中進行了自定義查詢。不幸的是,這個bean無法創建,因爲自定義查詢有某種錯誤。

實體

@Entity 
@Transactional 
@Table(name = "bericht") 
@Proxy(lazy = false) 
@Embeddable 
public class Bericht implements Serializable { 
    @Id 
    @GeneratedValue 
    private Integer id; 

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) 
    @JoinColumn(name = "PARENT_ID") 
    private Bericht parent; 
} 

接口

@Transactional 
public interface BerichtRepository extends JpaRepository<Bericht, Integer> { 
    @Query("SELECT b1 FROM Bericht b join Bericht b1 WHERE b1.parent.id <> NULL AND b1.parent.id = b.id AND b.id = ?1 order by b1.id desc") 
    public List<Bericht> getChildrenVanBericht(Integer id); 

    public default void deleteBericht(Integer id) { 
     List<Bericht> kinderen = getChildrenVanBericht(id); 

     for(Bericht kind:kinderen) { 
      if(getChildrenVanBericht(kind.getId()).size()==0) { 
       this.delete(kind); 
      } else { 
       deleteBericht(kind.getId()); 
      } 
     } 
    } 
} 

正如所看到的我要開始從票數的底部刪除Archy通過deleteBericht方法,並在層次結構中向上工作。

有沒有比上面顯示的deleteBericht方法更好的解決方案?

+0

您是否只有兩級層次結構(父級及其子級)或層級結構可以是多級(父級,子級,孫輩等)?如果是多層次的,應該刪除級聯到被刪除節點下的整個樹或者它的直接子節點(如果只是直接子節點,那麼孫子們應該怎麼辦?)?父母是否可以有多個孩子(如果是,您的父母 - 孩子映射被錯誤地聲明爲「@ OneToOne」而不是「@ ManyToOne」)? – manish

回答

0

首先,你的基本映射有一些問題。如果它是一個實體,它不應該有@Embeddable註釋。此外,@Entity上不應有@Transactional

無論如何,我希望,你應該能夠以正常的方式來刪除,如果你是做關係雙向如下:

@Entity 
@Table(name = "bericht") 
@Proxy(lazy = false) 
public class Bericht implements Serializable { 

    @OneToOne(mappedBy = "parent", cascade = CascadeType.DELETE) 
    private Bericht child; 

    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) 
    @JoinColumn(name = "PARENT_ID") 
    private Bericht parent; 

    //additionally always ensure both sides of the relationship are consistent 

    public void setChild(Bericht child){ 
     this.child = child; 
     child.parent = this; 
    } 

    public void setParent(Bericht parent){ 
     this.parent = parent; 
     parent.child = this; 
    } 
} 

現在刪除Bericht實例時,任何兒童應自動刪除。

Bericht b = //some Bericht 
berichtRepository.delete(b);// should cascade down through all children 
0

首先儘量避免復發,總是有風險的。

我的目的,你的其他的解決方案,得到所有的kind.id列表,然後做出一個SQL刪除像Query s = entytiManager.createQuery("Delete * From KindTable k Where k.id In (:kIdLst)");並通過q.setList("kIdLst", kindIds);

好運提供kIdLst! Z

+0

遞歸......風險?是吧?我在0類問題的類中使用遞歸關係。任何值得其資金的JPA提供者都應該能夠處理這些基本的事情 –

+0

遞歸的風險與JPA無關,它與如果你沒有對數據量進行完全和明確的控制相關的事實以遞歸方法處理,你冒着一些內存不足或堆棧已滿的風險。還有一點就是如果你遞歸執行,如果你有100種,你會調用100個sql請求,並且請求數量的增長與類型數量成線性關係(即:100k => 100sql,1000k = > 1000sql,等等);無需遞歸,無論多少種類型,您都可以調用一個請求... – Zorglube