Issue
I have some classes (entities) with methods annotated by @PostLoad
, @PrePersist
etc. and classes has @EntityListeners
annotation. I want to disable processing of callback methods and listeners in my test environment.
Removing part of code is impossible because tests are run on CI server and I don't have any possibility to change code just for tests.
Is there any possibility to turn off callback methods and entity listeners in JPA 2 configuration? I use Hibernate.
Solution
I'm pretty sure this isn't possible. The annotated-entity mechanism is very static, which is why I stopped using it.
What I did instead in similar situations was to define interfaces for the entities to implement, something like this:
interface UpdateValidation{
void preUpdate();
}
interface PersistValidation{
void prePersist();
}
// etc.
Now define a single EntityListener that checks the entities for the above interfaces. In the @PreUpdate
method, check for UpdateValidation
, in the @PrePersist
method, check for PersistValidation
. Then delegate to the entity methods.
That way you have a single Listener that controls the entire functionality, and you can turn that listener on or off with XML configuration.
Update here's a complete implementation:
public class DelegatingEntityListener{
public interface PrePersistSupport{
void prePersist();
}
public interface PostPersistSupport{
void postPersist();
}
public interface PreRemoveSupport{
void preRemove();
}
public interface PostRemoveSupport{
void postRemove();
}
public interface PreUpdateSupport{
void preUpdate();
}
public interface PostUpdateSupport{
void postUpdate();
}
public interface PostLoadSupport{
void postLoad();
}
@PrePersist
public void prePersist(final Object entity){
if(entity instanceof PrePersistSupport){
((PrePersistSupport) entity).prePersist();
}
}
@PostPersist
public void postPersist(final Object entity){
if(entity instanceof PostPersistSupport){
((PostPersistSupport) entity).postPersist();
}
}
@PreRemove
public void preRemove(final Object entity){
if(entity instanceof PreRemoveSupport){
((PreRemoveSupport) entity).preRemove();
}
}
@PostRemove
public void postRemove(final Object entity){
if(entity instanceof PostRemoveSupport){
((PostRemoveSupport) entity).postRemove();
}
}
@PreUpdate
public void preUpdate(final Object entity){
if(entity instanceof PreUpdateSupport){
((PreUpdateSupport) entity).preUpdate();
}
}
@PostUpdate
public void postUpdate(final Object entity){
if(entity instanceof PostUpdateSupport){
((PostUpdateSupport) entity).postUpdate();
}
}
@PostLoad
public void postLoad(final Object entity){
if(entity instanceof PostLoadSupport){
((PostLoadSupport) entity).postLoad();
}
}
}
And in case you wondered: no, I didn't write the code by hand. Here's the code that wrote that code :-) You can easily adjust it to your own needs.
public static void main(final String[] args){
final StringBuilder ib = new StringBuilder(); // interface builder
final StringBuilder sb = new StringBuilder(); // method builder
for(final Class<? extends Annotation> annotationType : Arrays
.asList(
// all lifecycle annotations:
PrePersist.class, PostPersist.class, PreRemove.class,
PostRemove.class, PreUpdate.class, PostUpdate.class,
PostLoad.class)){
final String annotationName = annotationType.getSimpleName();
final String lower =
annotationName
.substring(0, 1)
.toLowerCase()
.concat(annotationName.substring(1));
ib.append("public interface ")
.append(annotationName)
.append("Support{\n\tvoid ")
.append(lower)
.append("();\n}\n\n");
sb.append('@')
.append(annotationName)
.append(" public void ")
.append(lower)
.append("(Object entity){\nif(entity instanceof ")
.append(annotationName)
.append("Support){((")
.append(annotationName)
.append("Support)entity).")
.append(lower)
.append("();}}\n\n");
}
System.out.println(ib.toString());
System.out.println(sb.toString());
}
The drawback is of course that the JPA provider can't cache the lifecycle methods that are actually used, but I'd say this is the only way to get what you want / need.
Answered By - Sean Patrick Floyd
Answer Checked By - Marie Seifert (JavaFixing Admin)