Search code examples
javahibernatejpaeclipselinklifecycle

private callback methods with same name


I found that

A class is permitted to override an inherited callback method of the same callback type, and in this case, the overridden method is not invoked.

@MappedSuperclass
class Parent {
    @PrePersist
    protected void _PrePersist() { // <--+
    }                              //    |
}                                  //    |
                                   //    |
@Entity                            //    |
class Child {                      //    |
    @PrePersist                    //    |
    @Override                      //    |
    protected void _PrePersist() { //    |
        super._PrePersist(); // ---------+
    }
}

Question: What about private scope?

The callback methods can have public, private, protected, or package level access, but must not be static or final.

@MappedSuperclass
class Parent {
    @PrePersist
    private void _PrePersist() {
        // not invoked.
        // is this method still, technically, 'overridden'?
    }
}

@Entity
class Child {
    @PrePersist
    private void _PrePersist() {
        // no way to invoke super._PrePersist().
        // is this method still, technically, 'overriding' the parent's?
    }
}

In this case, Parent#_PrePersist() not invoked. Is this normal?

I tested with EclipseLink and Hibernate


Solution

  • Java classes do not inherit annotations automatically. In this case the JPA specification states that the @PrePersist annotation can be inherited by children - this is an implementation detail thats handled by the JPA provider (not by the virtual machine). So in your case, you can actually remove the @PrePersist annotation in the child class:

    @Entity
    class Child {
        @Override
        protected void _PrePersist() {
            super._PrePersist(); 
        }
    }
    

    Now, regardless of whether the JPA provider allows for inheritance of the @PrePersist annotation or not, all Java language rules fully apply. Which in this case you cannot override a private method of a superclass in a child class - that's not allowed per the Java specification and so, of course, won't work for JPA either.

    In effect you have two sets of rules at play here, the JPA rules and Java specification rules, and your code has to comply to both.