2016-01-06 64 views
0

我正在研究一些使用hibernate實現的web服務。問題是我需要訪問實體表的名稱(比如@Table(「Table_A」))。 代碼生成了,所以我不能改變實體類自己給我我需要的東西。這是緩存反射數據的正確方法嗎?

這是我到目前爲止做:

public static 
<T extends Entity<K>, K extends Serializable> 
String getTableName(Class<T> objClass) { 
    Table table = objClass.getAnnotation(Table.class); 
    return (table != null)? table.name() : null; 
} 

然而,經過一番研究,我發現,反思是不是最好的性能,明智的,因爲這種方法將被調用了很多我在尋找另一種方式去實現它。

我試圖按照這裏給出的建議: Performance of calling Method/Field.getAnnotation(Class) several times vs. Pre-caching this data in a Map

這是我想出了:

public final class EntityUtils { 
    private static HashMap<String, String> entityCache; 

    private EntityUtils() { 
     entityCache = new HashMap<String, String>(); 
    } 

    public static 
    <T extends Entity<K>, K extends Serializable> 
    String getTableName_New(Class<T> objClass) { 
     String tableName = entityCache.get(objClass.getCanonicalName()); 

     if (tableName == null) { 
      Table table = objClass.getAnnotation(Table.class); 

      if (table != null) { 
       tableName = table.name(); 
       entityCache.put(objClass.getCanonicalName(), tableName); 
      } 
     } 

     return tableName; 
    } 
} 

但是,我不知道這件事。在靜態地圖中緩存反射數據是一個好主意嗎?有沒有其他方法可以實現這一目標?

+1

注如果沒有指定'@ Table'註釋,那麼Sean的答案中的key.getSimpleName()就是缺省表名。添加這個功能還有一個好處,那就是確保在你的地圖上爲每個請求的類添加一個etry。在您的實際代碼中,缺少一個'@ Table'註釋將始終執行反射查找以僅查找null。 – A4L

回答

2

理想情況下,我會使用一個帶有弱鍵的Guava緩存,這樣您在使用某些高級ClassLoader魔法時就不會保留對類對象的任何引用。

LoadingCache<Class<?>, String> tableNames = CacheBuilder.newBuilder() 
     .weakKeys() 
     .build(
      new CacheLoader<Class<?>, String>() { 
      public String load(Class<?> key) { 
       Table table = objClass.getAnnotation(Table.class); 
       return table == null ? key.getSimpleName() : table.name(); 
      } 
      }); 

用法:

String tablename = tableNames.get(yourClass); 

參見:Caches Explained


在另一方面:註釋是由JDK緩存也,所以你以前的做法可能是罰款

相關問題