通过自动发现加载动态创建的实体
我必须使用一个奇怪的数据库结构,在生产中可能有更多的表但具有相同的列。我们希望使用 JPA (Hibernate) 通过实体/JPQL 查询来处理它们。这个想法是在运行时在 JVM 中动态地为每个表创建实体类。这种方法效果很好。我使用 Javassist 创建实体 - 使用已经存在的已编译实体,并动态向其添加注释(实体、表):
public Class generateGroupStateEntity(String className,String tableName) {
ClassPool cp = ClassPool.getDefault();
InputStream is = new FileInputStream(new File("MyTemplateEntity.class"));
CtClass c = cp.makeClass(is);
c.setName(className);
ClassFile cf = c.getClassFile();
ConstPool constPool = cf.getConstPool();
AnnotationsAttribute annotAtr = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
Annotation annot = new Annotation("javax.persistence.Entity", constPool);
annotAtr.addAnnotation(annot);
Annotation annotTable = new Annotation("javax.persistence.Table", constPool);
annotTable.addMemberValue("name", new StringMemberValue(tableName,cf.getConstPool()));
annotAtr.addAnnotation(annotTable);
cf.addAttribute(annotAtr);
return c.toClass();
}
当我从 Configuration 对象手动构建 Hibernate SessionFactory 时,使用 addAnnotatedClass 方法将此类添加到 Configuration 中,它工作正常。问题在于自动发现,当我在 spring 上下文中使用包扫描时,JPA 或 AnnotationSessionFactoryBean 均未发现/找到该实体。 (我得到:“QuerySyntaxException:[MyEntity] 未映射”异常)
Class.forName(myNewEntityName) 有效,这意味着它是在类加载器中初始化的。
(当然我知道这不是处理这些桌子的理想设计模式。)
问题是为什么以及如何放置它?
(Javassist 3.15.0-GA、hibernate 核心 3.6.6.Final、hibernate-entitymanager 3.5.6-Final)
I have to work with a strange DB structure, where on production there could be more tables but with same columns. And we want to use JPA (Hibernate) with handle them, by entities/JPQL queries. The idea is to create entity classes for each table dynamically within JVM at runtime. This approach works fine. I create Entities with Javassist - using an already existing compiled entity, and I add annotations to it dynamically (Entity, Table):
public Class generateGroupStateEntity(String className,String tableName) {
ClassPool cp = ClassPool.getDefault();
InputStream is = new FileInputStream(new File("MyTemplateEntity.class"));
CtClass c = cp.makeClass(is);
c.setName(className);
ClassFile cf = c.getClassFile();
ConstPool constPool = cf.getConstPool();
AnnotationsAttribute annotAtr = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
Annotation annot = new Annotation("javax.persistence.Entity", constPool);
annotAtr.addAnnotation(annot);
Annotation annotTable = new Annotation("javax.persistence.Table", constPool);
annotTable.addMemberValue("name", new StringMemberValue(tableName,cf.getConstPool()));
annotAtr.addAnnotation(annotTable);
cf.addAttribute(annotAtr);
return c.toClass();
}
When I build a Hibernate SessionFactory by hand, from a Configuration object, adding this classes using addAnnotatedClass method to Configuration, it works fine. Problem is with automated discovery, the entity is not discovered/found neither by JPA, or by AnnotationSessionFactoryBean - when I use package scanning with within a spring context.
(I get: "QuerySyntaxException: [MyEntity] is not mapped" exception)
Class.forName(myNewEntityName) works that means the it is Initialized within the Classloader.
(Of course I know this is not an Ideal design patter for Handling these tables.)
The question is why and how to sole it?
(Javassist 3.15.0-GA, hibernate core 3.6.6.Final, hibernate-entitymanager 3.5.6-Final)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为包扫描发生在类路径中的 jar 和文件夹上 - 而不是在类加载器级别。这是为了优化不将所有类加载到内存中。这篇文章详细介绍了如何完成了。
要解决这个问题,您可能必须扩展 AnnotationSessionFactoryBean - 并动态添加类列表。
I think package scanning happens on the jars and folder in the classpath - not at the classloader level. This is to optimize not loading all the classes into memory. This article has some details of how it is done.
To solve it you might have to extend the AnnotationSessionFactoryBean - and add the list of classes dynamically.