2014-06-25 49 views
1

我們有一個場景,其中某個包中的實體類與其他所有其他包中的實體類不同。我試圖在@Table註釋上使用PersistenceUnitPostProcessors在運行時使用javaassist設置目錄和架構,如下所示。Spring數據JPA + Hibernate:在運行時將目錄/架構注入到JPA實體

問題:在javaassist註釋中添加的成員值不會反映到與其關聯的實際類上。請幫我找到錯誤的代碼行;或者如果還有其他方法可以實現這一點,那麼很高興知道。

注意:我不想爲每個目錄/模式組合創建單獨的EntityManagerFactory - 由於數據源相同,因此我們並不需要這樣做。

在Spring上下文

相關內容:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

<tx:annotation-driven />  

<bean name="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
<property name="dataSource" ref="dataSource" /> 
<property name="persistenceUnitName" value="mainUnit" /> 
    <property name="packagesToScan" value="com.mycompany.lob.domain" />  
    <property name="jpaVendorAdapter"> 
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
    </property> 
    <property name="persistenceUnitPostProcessors"> 
    <list> 
     <bean class="com.mycompany.lob.jpa.CustomPersistenceUnitPostProcessor"/> 
    </list> 
    </property> 
    <property name="jpaProperties"> 
    <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.SqlmxDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.format_sql">true</prop> 
      <prop key="hibernate.jdbc.batch_size">100</prop> 
      <prop key="hibernate.order_inserts">true</prop> 
      <prop key="hibernate.cache.use_second_level_cache">true</prop> 
      <prop key="hibernate.connection.autocommit">true</prop> 
      <prop key="hibernate.default_schema">DEFAULT_SCHEMA</prop> 
      <prop key="hibernate.default_catalog">DEFAULT_CATALOG</prop> 
    </props> 
    </property> 
</bean> 

PersistenceUnitPostProcessors回調:

public class CustomPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor { 
@Value("${user.schema}") 
private String userSchema; 
@Value("${user.catalog}") 
private String userCatalog; 
private static final Logger LOGGER = LoggerFactory.getLogger(CustomPersistenceUnitPostProcessor.class); 
@SuppressWarnings("unchecked") 
@Override 
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) { 
    LOGGER.info("MutablePersistenceUnitInfo : {} ",pui); 
    List<String> jpadomains = pui.getManagedClassNames(); 
    for (Iterator<?> iterator = jpadomains.iterator(); iterator.hasNext();) { 
     String clazzName = (String) iterator.next(); 
     if(clazzName.startsWith("com.mycompany.lob.domain.user")){ 
      try { 
      //modify annotation attributes using JavaAssist 
      ClassPool pool = ClassPool.getDefault(); 
      CtClass ctClass = pool.get(clazzName); 
      ClassFile classFile = ctClass.getClassFile(); 
      ConstPool constPool = classFile.getConstPool(); 
      AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute)classFile.getAttribute(AnnotationsAttribute.visibleTag); 
      if(annotationsAttribute!=null){ 
      //Get hold of @Table annotation 
       Annotation tableAnnotation = annotationsAttribute.getAnnotation("javax.persistence.Table"); 
       if(tableAnnotation!=null){ 
        tableAnnotation.addMemberValue("catalog", new StringMemberValue(userCatalog, constPool)); 
        tableAnnotation.addMemberValue("schema", new StringMemberValue(userSchema, constPool)); 
        annotationsAttribute.addAnnotation(tableAnnotation); 
        LOGGER.debug("Schema-Table : {} - {} ", ((StringMemberValue)tableAnnotation.getMemberValue("schema")).getValue(), 
                 ((StringMemberValue)tableAnnotation.getMemberValue("name")).getValue()); 
        //write the file back 
        ctClass.writeFile(); 
       } 

      } 
      } catch (Exception e) { 
       LOGGER.error("Schema/Catalog could not be altered for {} ",clazzName); 
      } 
     } 
    } 

} 

} 
+0

這不會有任何效果,這些類已經加載和休眠掃描。因爲映射元數據已經生成,所以之後改變表值不會起作用。包括和[orm.xml](http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/xml-overriding.html)並將其外化。在LocalContainerEntityManagerFactoryBean上設置'MappingResources'屬性來加載外部文件以獲得額外的映射/覆蓋。 –

+0

@M。 Deinum - 如果對具有不同目錄/模式組合的實體使用'MappingResources',彈簧屬性佔位符不能用於注入特定於環境的值。 **另一種觀察:**當我使用'ctClass.toClass()'替換'ctClass.writeFile()'時,註釋屬性更改開始顯示對原始類的影響,至少來自jUnit - 不確定它在部署時的表現如何在應用程序服務器上。 – aRvi

回答

1

答案很簡單: 19. Multitenancy

複雜的目錄映射:Hibernate v5中的interface PhysicalNamingStrategy很有幫助。

public interface PhysicalNamingStrategy { 
    public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment); 
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment); 
    .... 
} 

檢查Example 2. Example PhysicalNamingStrategy implementationHibernate 5 User Guidehow to config it

相關問題