简体   繁体   中英

Java JpaRepository @Query join own table

I have an entity class where each instance can have a parent of the same type.

Now I want to be able to delete a parent object, and in the process delete all its children with it. I couldn't do it via a cascade type so I made a custom query in my JPA repository. Unfortunately this bean could not be created because the custom query has some kind of error.

Entity class

@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;
}

Repository interface

@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());
            }
        }
    }
}

As seen I want to start deleting from the bottom of the hierarchy via the deleteBericht method and work upwards in the hierarchy to the top.

Is there a better solution out there than the deleteBericht method as shown above?

First of all try to avoid recurcivity, it's always risky.

I purpose you an other solution, get the list of all the kind.id then make an SQL delete like Query s = entytiManager.createQuery("Delete * From KindTable k Where k.id In ( :kIdLst )"); and provide kIdLst through q.setList("kIdLst", kindIds);

Good luck ! Z

Firstly you have some problems with your basic mapping. If it's an Entity it shouldn't have the @Embeddable annotation. Additionally, you shouldn't have @Transactional on an @Entity .

Anyway, I would expect that you should be able to delete in the normal way if you were to make the relationship bi-directional as below:

@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;
    }
}

Now when deleting a Bericht instance any children should be deleted automatically.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM