Entity listener does not run correctly in JPA

0

I'm having trouble running the listeners correctly in JPA.

The project uses:

JPA 2.1.

EclipseLink 2.6.3

MySql 5.7.11

I have an author entity marked with the annotation OneToMany and orphanRemoval = true to the entity Book, when in the author entity I delete the reference to a book and try to update it, no listener of the book class is running.

I add the code so you can see what it is about.

@Entity
@Table(name = "ges_autor")
public class Autor  implements Serializable, ItemIf {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @OneToMany(mappedBy = "autor",cascade = {CascadeType.ALL},  fetch = FetchType.LAZY, orphanRemoval = true)
    //@PrivateOwned he probado poniendola y tampoco funciona
    protected List<Libros> libros;

//getters y setters
}

@Entity
@Table(name = "ges_libro")
@EntityListeners({LibroListener.class})
public class Libro implements Serializable, ItemIf {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

    @ManyToOne
    @JoinColumn(name="autor_id")
    protected Autor autor;

//getters y setters
}



public class LibroListener {
    @PrePersist
    private prePersist(Libro libro){
         System.out.println("Listener libro persist ejecutado");
    }
    @PreUpdate
    private preUpdate(Libro libro){
         System.out.println("Listener libro update ejecutado");
    }
    @PreRemove
    private preRemove(Libro libro){
        System.out.println("Listener libro remove ejecutado");
    }
}

To reproduce the error, simply load an author of the database, delete a book and make a merge.

Autor autor = getFacade().find(id);
autor.getLibros().remove(libro);
getFacade().merge(autor);

The orphanRemoval annotation works and the book is deleted from the database but no listener is running.

    
asked by Javi2EE 16.06.2016 в 18:00
source

2 answers

1

The cause of the problem is a bug in the EclipseLink implementation, as specified here (Thanks @Mitsu for the link) the preremove method should run after an orphanRemoval, but the truth is that it is not running. The only reference to this bug was found in the eclipse forum .

I have not seen that the bug was officially reported and I have not opened any, it is the second important bug I find in EclipseLink the last month. This has made me decide to start the titanic task of changing everything to Hibernate, which has been around for a long time now and I have left EclipseLink aside once and for all.

Greetings

    
answered by 23.06.2016 / 16:00
source
0

First we make merge and then remove . This is because merge loads the contents of the database to update it (it is synchronized). This is not a bug, but that's how JPA works.

So, if what you want to do is just delete, it was enough:

Autor autor = getFacade().find(id);
autor.getLibros().remove(libro); // no es necesario merge ni commit

But if what you want is to update some books and eliminate others, it would be:

Autor autor = getFacade().find(id);
getFacade().merge(autor);
autor.getLibros().remove(libro);
getFacade().merge(autor);

On the other hand, if you had done find of the user from another method in another layer, for example, a view, to do certain operations such as removing or updating books, and then call a method to update, then only the merge would be necessary. Since, since you have orphanRemoval=true in your relation @OneToMany , books that were not in List or Collection would automatically be deleted. That is, it would only be necessary:

getFacade().merge(autor);
    
answered by 16.05.2017 в 00:04