我們有一個場景,其中某個包中的實體類與其他所有其他包中的實體類不同。我試圖在@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);
}
}
}
}
}
這不會有任何效果,這些類已經加載和休眠掃描。因爲映射元數據已經生成,所以之後改變表值不會起作用。包括和[orm.xml](http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/xml-overriding.html)並將其外化。在LocalContainerEntityManagerFactoryBean上設置'MappingResources'屬性來加載外部文件以獲得額外的映射/覆蓋。 –
@M。 Deinum - 如果對具有不同目錄/模式組合的實體使用'MappingResources',彈簧屬性佔位符不能用於注入特定於環境的值。 **另一種觀察:**當我使用'ctClass.toClass()'替換'ctClass.writeFile()'時,註釋屬性更改開始顯示對原始類的影響,至少來自jUnit - 不確定它在部署時的表現如何在應用程序服務器上。 – aRvi