我有一些類(實體)的方法由@PostLoad,@PrePersist等註解,類有@EntityListeners註釋。我想在我的測試環境中禁用處理回調方法和偵聽器。如何禁用JPA 2回調方法和實體監聽器
刪除部分代碼是不可能的,因爲在CI服務器上運行測試,並且我沒有任何可能爲測試更改代碼。
有沒有可能在JPA 2配置中關閉回調方法和實體監聽器?我使用Hibernate。
我有一些類(實體)的方法由@PostLoad,@PrePersist等註解,類有@EntityListeners註釋。我想在我的測試環境中禁用處理回調方法和偵聽器。如何禁用JPA 2回調方法和實體監聽器
刪除部分代碼是不可能的,因爲在CI服務器上運行測試,並且我沒有任何可能爲測試更改代碼。
有沒有可能在JPA 2配置中關閉回調方法和實體監聽器?我使用Hibernate。
我很確定這是不可能的。註釋實體機制非常靜態,這就是爲什麼我停止使用它。
我做了什麼,而不是在類似情況下被定義實體接口來實現,這樣的事:
interface UpdateValidation{
void preUpdate();
}
interface PersistValidation{
void prePersist();
}
// etc.
現在定義一個EntityListener來檢查上述接口的實體。在方法中,檢查UpdateValidation
,在@PrePersist
方法中檢查PersistValidation
。然後委託給實體方法。
通過這種方式,您可以使用單個監聽器來控制整個功能,並且可以使用XML配置打開或關閉該監聽器。這裏
更新是一個完整的實現:
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();
}
}
}
而如果你想知道:沒有,我沒有手工編寫代碼。以下是編寫該代碼的代碼:-)您可以根據自己的需要輕鬆調整它。
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());
}
缺點當然是JPA提供者不能緩存實際使用的生命週期方法的,但我會說這是得到你想要/需要什麼的唯一方式。
如果您想從Hibernate 4.3.5(我測試過的唯一一個)中刪除所有JPA偵聽器,可以完成。我將不會展示如何獲得EntityMangerFactory(下面的代碼中的emf),但在此之後應該添加/運行下面的代碼。
說明:似乎有一個包含所有已註冊的監聽器和回調的實體稱爲org.hibernate.jpa.event.internal.jpa.CallbackRegistryImpl
一個非常核心的類。通過用空的替換註冊表不會執行回調。
SessionFactoryImpl sessionFactory = (SessionFactoryImpl) ((EntityManagerFactoryImpl) emf).getSessionFactory();
EventListenerRegistry eventListenerRegistry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
CallbackRegistryImpl emptyRegistry= new CallbackRegistryImpl();
for (EventType eventType : EventType.values()) {
final EventListenerGroup eventListenerGroup = eventListenerRegistry.getEventListenerGroup(eventType);
for (Object listener : eventListenerGroup.listeners()) {
if (CallbackRegistryConsumer.class.isInstance(listener)) {
((CallbackRegistryConsumer) listener).injectCallbackRegistry(emptyRegistry);
}
}
}
這樣的編譯沒有()的嗎? PostUpdateSupport {而不是PostUpdateSupport(){? – 2011-03-23 17:30:37
@Chris我不太瞭解你。隨意將代碼粘貼到IDE中並親自查看。上面的代碼*進行編譯,並且強制轉換(以及括號)是必需的。 – 2011-03-23 17:34:44
肖恩,thx很多:D就是這樣。 – 2011-03-23 18:07:14