1

I'm trying to determine wether or not it is possible to delete an object from the repository. In other words: If a delete would result in a DataIntegrityViolationException or not. This is meant to hide the "Delete" button on the frontend, if a delete is not possible.

Example: I got classes A and B:

@Entity
public class A{
    @Id
    private UUID id;

    @Column
    private String name;

    @ManyToMany
    private Set<B> bs= new HashSet<>();

    //getter, setter, equals,...
}
@Entity
public class B{
    @Id
    private UUID id;

    @Column
    private String name;

    //getter, setter, equals,...
}

Now if I want to delete an object of B, which is in any A objects set, I will get a "DataIntegrityViolationException". Of course since the object is actively in use as a key.

I thought about checking A first, to see if there are any references and I can safely delete my B instance. But in practise this might be a bit tricky, since more than one class could use class B and the other classes would be added later by someone else, not familiar with the code. Also this...

aRepository.findAll(Example.of(new A(null, null, new HashSet<>(Array.asList(b))));

only delivered absolute trash as a result (>20+ objects for a b used nowhere).

A second thought was by just trying something like this:

    @Transactional //always roll back
    public void inUse(B b) throws TransacationException{
        bRepository.delete(composition);
        throw new TransacationException();
    }

and then checking it like this:

    public Boolean deleteAble(B b){
        try{
            inUse(b);
        } catch (DataIntegrityViolationException e){
            return false; // constraint violation --> in use!
        } catch (TransacationException e){
            return true;
        }
    }

Unfortunately none of these approaches seem to work. Have you got any idea on how to solve this problem?

floo
  • 57
  • 5
  • 2
    Many to many implies having an intermediate table where id's on type A referenced by id's of type B. A simple check for a presence of id in this table would determine that the data has a reference, thus cannot be deleted. – Artyom Rebrov Jun 04 '19 at 18:52
  • Of course this table exists, but is managed entirely by Spring Data and I'm not really aware of a good method of accessing this table without having to implement it manually. Also this does not cover for the case, that a entitiy I'm not aware of might reference to me. – floo Jun 04 '19 at 19:01
  • 1
    Possible duplicate of this - https://stackoverflow.com/questions/17392207/hibernate-check-deletion-constraints – SRm Jun 04 '19 at 19:10
  • 1
    This might help too - https://stackoverflow.com/questions/2109476/how-to-handle-dataintegrityviolationexception-in-spring – Ajay Kumar Jun 04 '19 at 19:18

1 Answers1

1

Maybe you could make your @ManyToMany association bidirectional, like adding this to your class B:

@ManyToMany(mappedBy = "bs")
private Set<A> as = new HashSet<>();

Then it would be only like:

someB.getAs().isEmpty()
pirho
  • 11,565
  • 12
  • 43
  • 70
  • I agree, that this would prevent a lot of trouble, but unfortunately this does not seem applicable in this particular case :( – floo Jun 05 '19 at 14:02
  • @floo Is it you cannot change B or do you get some error? In case of just not working you could try explicitly declaring the many2many mapping table instead letting JPA create it from default. If you have previous mapping table already existing from the previous tries it might not work correctly. – pirho Jun 06 '19 at 06:37