【发布时间】:2014-06-25 08:12:53
【问题描述】:
我们有一个场景,在目录/模式组合中,某个包内的实体类与所有其他包中使用的默认实体类不同。我正在尝试使用 PersistenceUnitPostProcessors 在运行时使用 javaassist 回调在 @Table 注释上设置目录和架构,如下所示。
问题: 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 并将其外部化。在
LocalContainerEntityManagerFactoryBean上设置MappingResources属性以加载外部文件以进行其他映射/覆盖。 -
@M. Deinum - 如果我将
MappingResources用于具有不同目录/模式组合的实体,则不能使用弹簧属性占位符来注入特定于环境的值。 另一个观察结果:当我用ctClass.toClass()替换ctClass.writeFile()时,注释属性更改开始对原始类产生影响,至少来自jUnit - 不确定它在部署到应用服务器时会如何表现。
标签: spring hibernate jpa runtime schema